【JVM】内存管理

2023-11-04

目录

引言

1.内存分配

1.0 创建一个对象涉及的内存  

1.1 方法区

1.2 堆

1.2.1 对象(堆里的存储单元)

2.1.3 虚拟机栈

2 垃圾回收GC

2.1 垃圾回收的目标区域

2.2 垃圾回收算法

2.2.0 标记算法

2.2.1 标记-清除(Mark-Sweep)

2.2.2 标记-复制

2.2.3 标记-整理

2.2.4 分代收集

2.3 垃圾收集器

2.3.1 年轻代

2.3.2 老年代

2.3.3 分代收集器


引言

Java技术体系的自动内存管理,最根本的目标是自动化地解决两个问题:自动给对象分配内存以及自动回收分配给对象的内存。

1.内存分配

JVM规范中指定运行时数据去分为以下几块,方法区、堆、程序计数器、虚拟机栈、本地方法栈。

其中方法区、堆是所有线程共享的,而程序计数器、虚拟机栈、本地方法栈是线程私有的。

    

线程共享? jvm规范 hotspot实现 存放内容 可能异常 hotspot选项控制
共享 方法区

永久代

1.8 元空间

存放加载的

类信息包含常量池、静态变量

OutOfMemoryError: PermGen space 

-XX:MaxPermSize=64m
堆 

堆-年轻代

堆-老年代

对象&数组,

最大的一块内存

gc管理的主要区域

OutOfMemoryError:

Java heap space

-Xms128m

-Xmx700m

-XX:NewRatio=2

私有 PC程序计数器 PC程序计数器 下一条字节码指令地址 不会发生内存溢出  
虚拟机栈 执行java字节码的栈 StackOverflowError -Xss
本地方法栈 JNI调用的执行机器码栈帧

1.0 创建一个对象涉及的内存  

包含中引用、中对象、方法区-类信息,如下如,以上的3中区域内存通过如下方式串联

  1. 方法区加载对应的(当前类及其父类、依赖类)
  2. 堆中分配内存存放对象实例,对象头中引用指向方法区类型信息
  3. 栈中分配局部变量引用到对象实例

1.1 方法区

JVM规范中的方法区,在hotspot(jdk1.8以前)安排在堆中永久代,JDK1.8以后成为元空间

包含类信息和运行时常量池

运行时常量池是每个类或者接口的类文件中的常量池的运行时内存存储区域,

常量池保存代码中的字面量、类名等,如一行String str = "123";"123"和"java.lang.String"等等常量。

 

1.2 堆

这是被所有线程共享的一块内存区域,其中存放的是对象实例本身以及数组对象。也是GC最频繁的一块区域

HotSpot虚拟机为了把GC分代收集扩展至方法区,堆进一步划分为,

当JVM启动参数:-Xms20M -Xmx20M -Xmn20M

 

1.2.1 对象(堆里的存储单元)

堆的存储单元是一个对象,一个对象包含对象头实例数据对象头又包含Mark Word元数据指针。

对象内存分配策略:

  1. 对象优先在Eden分配 
  2. 大对象直接进入老年代   
    • 大 阈值 -XX:PretenureSizeThreshold=3145728(3M)
  3. 长期存活的对象将进入老年代 
    • 每熬过一次Minor GC,年龄就加1岁,-XX:MaxTenuringThreshold设置 default 15 ,CMS default=6

2.1.3 虚拟机栈

虚拟机栈主要包含局部变量表、操作数栈、动态链接和方法出口,局部变量表中存储着指向对象的引用。

2 垃圾回收GC

2.1 目标区域和实际

full?   解释 时机
部分收集(Partial GC)

新生代收集

(Minor GC/Young GC)

只是新生代 创建新对象在Eden申请空间失败时

老年代收集

(Major GC/Old GC)

只是老年代

只有CMS收集器会有单独收集老年代的行为

请注意“Major GC”这个说法现在有点混淆,

在不同资料上常有不同所指,

读者需按上下文区分到底是指老年代的收集还是整堆收集。

 
混合收集(Mixed GC)

整个新生代以及部分老年代

只有G1收集器会有这种行为

 
整堆收集(Full GC) 收集整个Java堆和方法区的垃圾收集 Eden、survivor不足,判断老年代是否充足,不充足触发full gc
  1. 堆内存中的不可用的对象

  2. 方法区中废弃的常量和无用的类进行回收

2.2 垃圾回收算法

2.2.0 标记算法

你是什么垃圾??判断垃圾方法包括引用计数法和可达性分析法

(1)引用计数法

每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时表示可以回收。

优缺点:此方法简单,但无法解决对象相互循环引用的问题。因此Java虚拟机未采用该种方法

(2)可达性分析法

CMS、G1、ZGC等收集器使用此标记方法,在遍历GC roots需要

从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,即为不可达对象,会被判定为可回收的对象。

GC Roots包括:

  1. * 虚拟机栈中局部变量
  2. * 本地方法JNI(即native方法)
  3. * 方法区类静态变量
  4. * 方法区常量

2.2.1 标记-清除(Mark-Sweep)

大名鼎鼎的CMS就是这类算法啦。

实现原理:首先标记出需要回收的对象,标记完成后,统一回收掉被标记的对象,也可反过来标记存活的对象,统一回收未标记的对象。

标记过程就是对象是否属于垃圾的判定过程,这在前一节讲述垃圾对象标记判定算法时其实已经介绍过了。

优势:算法简单,原地实现

劣势:内存碎片,大量可回收对象时执行效率低

2.2.2 标记-复制

“半区复制”(Semispace Copying),它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。

当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

优势:实现简单,运行高效

劣势:需要保留空闲内存,空间浪费。

新生代的回收器大部分都是用这个算法,且做了优化,不用浪费那么多,一般浪费1/10。

HotSpot虚拟机默认Eden和Survivor的大小比例是8∶1,也即每次新生代中可用内存空间为整个新生代容量的90%(Eden的80%加上一个Survivor的10%),只有一个Survivor空间,即10%的新生代是会被“浪费”的。

2.2.3 标记-整理

不是直接对可回收对象进行清理,而是让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存

优势:不浪费空间,没有内存碎片

劣势:对象存活率较高时就要进行较多的移位操作,效率将会降低

2.2.4 分代收集

  • 指的是针对不同分代的内存区域,采用不同的垃圾回收算法
  • 年轻代一般采用复制算法,老年代则一般采用标记-整理算法

2.3 垃圾收集器

2.3.1 年轻代

采用上节中所说的复制算法

  • Serial 复制
  • ParNew 复制
  • Parallel Scavenge 复制

2.3.2 老年代

  • CMS 清除
  • Serial Old 整理
  • Parallel Old 整理

2.3.3 分代收集器

G1 Garbage First,JDK 9发布之日,G1宣告取代Parallel Scavenge加Parallel Old组合,成为服务端模式下的默认垃圾收集器,而CMS则沦落至被声明为不推荐使用(Deprecate)的收集器。

基于Region的堆内存布局,G1不再坚持固定大小以及固定数量的分代区域划分,而是把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以按需扮演新生代的Eden空间、Survivor空间、老年代空间。Region大小:G1HeapRegionSize设定,取值范围为1MB~32MB。

收集器能够对扮演不同角色的Region采用不同的策略去处理,这样无论是新创建的对象还是已经存活了一段时间、熬过多次收集的旧对象都能获取很好的收集效果。

四个步骤:

  1. 初始标记(Initial Marking):仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS指针的值,让下一阶段用户线程并发运行时,能正确地在可用的Region中分配新对象。这个阶段需要停顿线程,但耗时很短。
  2. 并发标记(Concurrent Marking):从GC Root开始进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。当对象图扫描完成以后,还要重新处理SATB记录下的在并发时有引用变动的对象。
  3. 最终标记(Final Marking):对用户线程做另一个短暂的暂停,用于处理并发阶段结束后仍遗留下来的最后那少量的SATB记录。
  4. 筛选回收(Live Data Counting and Evacuation):负责更新Region的统计数据,对各个Region回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个Region构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧Region的全部空间。

G1 收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的 Region(它的名字 Garbage-First 的由来)。这种使用 Region 划分内存空间以及有优先级的区域回收方式,保证了 G1 收集器在有限时间内可以尽可能高的收集效率(把内存化整为零)。

目前在小内存应用上CMS的表现大概率仍然要会优于G1,而在大内存应用上G1则大多能发挥其优势,这个优劣势的Java堆容量平衡点通常在6GB至8GB之间。

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【JVM】内存管理 的相关文章

  • IntelliJ 调试:暂停整个虚拟机,然后进入单线程

    我正在调试一个具有大量线程的应用程序 我的断点设置为暂停整个虚拟机 当线程遇到其中一个断点时 我想使用 Step Over 但这似乎会恢复整个虚拟机 直到该步骤完成 如果我可以只单步执行到达断点的单个线程 那确实会有帮助 在 Intelli
  • 内存中的方法表示是什么?

    在思考一下 Java C 编程时 我想知道属于对象的方法如何在内存中表示 以及这一事实如何涉及多线程 是为内存中的每个对象单独实例化一个方法还是执行 同一类型的所有对象共享该方法的一个实例 如果是后者 执行线程如何知道哪个对象是 要使用的属
  • 是否可以使 java.lang.invoke.MethodHandle 与直接调用一样快?

    我正在比较性能MethodHandle invoke以及直接静态方法调用 这是静态方法 public class IntSum public static int sum int a int b return a b 这是我的基准 Stat
  • 将 JVM 字节码往返于文本表示的故障安全方法

    我正在寻找一种在 JVM 类文件和文本表示之间往返的故障安全方法 一项严格的要求是 只要文本表示形式保持不变 生成的往返 JVM 类文件在功能上与原始 JVM 类文件完全相同 此外 文本表示必须是人类可读和可编辑的 应该可以对文本表示进行小
  • JVM 规范更新

    JVM 规范第 2 版的日期是 1999 年 自那时以来 我应该考虑学习哪些重要更新 如动态调用 这当然是为了了解现代 JVM 实现的内部原理 特别是 HotSpot 访问此链接http wikis sun com display HotS
  • Lambda 性能改进,Java 8 与 11

    我对 lambda 与方法参考运行了一些 JMH 测试 看起来类似于 IntStream reduce Integer max vs IntSream reduce i1 i2 gt Integer max i1 i2 我注意到 在 Jav
  • 集群环境下的Spring Singleton

    正如中所讨论的this https stackoverflow com questions 1194129 singleton in cluster environmentpost 不适合使用单例聚集的环境 因为不同 JVM 中有多个单例对
  • JVM HotSpot 上的 Java 异常计数器

    我想知道是否可以在不更改应用程序代码的情况下记录 JVM 级别上发生的每个异常 我所说的每个异常是指捕获和未捕获的异常 我想稍后分析这些日志并按异常类型 类 对它们进行分组 并简单地按类型对异常进行计数 我正在使用热点 也许有更明智的理由这
  • 使用 + 符号连接字符串

    今天我在读书Antonio 关于 toString 性能的博客 https antoniogoncalves org 2015 06 30 who cares about tostring performance 还有一段话 昨天曾经被认为
  • 当 Java 中的集合超出容量时会发生什么?

    我有一个服务 它将所有对其进行的调用暂存在内存中 因为我们不想丢失数据 同时我们需要该服务因任何外部依赖项 例如数据库 而失败 然后 这些分阶段的调用会在后台例行接收和处理 如果出于任何原因 如果调用太多并且内存不足 我们就需要警惕 所以
  • 如何减少Scala中创建的对象数量?

    我正在 Scala 中编写一个计算机图形应用程序 它使用 RGB 类返回图像中某个点的颜色 正如你可以想象的 返回颜色 RGB 对象的函数被调用了很多次 class RGB val red Int val green Int val blu
  • 什么触发了java垃圾收集器

    我对 Java 中垃圾收集的工作原理有点困惑 我知道当不再有对某个对象的实时引用时 该对象就有资格进行垃圾回收 但是如果它有对实时对象的引用怎么办 可以说我有一个节点集合 它们再次引用更多节点 List 1 gt Node a gt Nod
  • 启用JConsole远程监控是否会影响生产中的系统性能?

    Oracle Sun 说只要不在生产环境中本地运行就可以吗 http download oracle com javase 1 5 0 docs guide management jconsole html http download or
  • Scala 对大数的阶乘有时会崩溃,有时不会

    以下程序经过编译和测试 有时返回结果 有时充满屏幕 java lang StackOverflowError at scala BigInt apply BigInt scala 47 at scala BigInt equals BigI
  • Scala REPL 中的递归重载语义 - JVM 语言

    使用 Scala 的命令行 REPL def foo x Int Unit def foo x String Unit println foo 2 gives error type mismatch found Int 2 required
  • Bipush 在 JVM 中如何工作?

    我知道 iload 接受整数 1 到 5 但是如何使用 bipush 指令扩展到更高的数字 特定整数如何与字节码一起存储 有几种不同的指令可用于推送整数常量 最小的是iconst 指令 这些只是一个字节 因为该值是在操作码本身中编码的 ic
  • 抛出 Java 异常时是否会生成堆栈跟踪?

    这是假设我们不调用 printstacktrace 方法 只是抛出和捕获 我们正在考虑这样做是为了解决一些性能瓶颈 不 堆栈跟踪是在构造异常对象时生成的 而不是在抛出异常对象时生成的 Throwable 构造函数调用 fillInStack
  • 通过SOCKS代理连接Kafka

    我有一个在 AWS 上运行的 Kafka 集群 我想用标准连接到集群卡夫卡控制台消费者从我的应用程序服务器 应用程序服务器可以通过 SOCKS 代理访问互联网 无需身份验证 如何告诉 Kafka 客户端通过代理进行连接 我尝试了很多事情 包
  • Scala 为了在 JVM 上运行做出了哪些妥协?

    Scala 是一种很棒的语言 但我想知道如果它有自己的运行时 如何改进 IE 由于 JVM 的选择 做出了哪些设计选择 我所知道的两个最重要的妥协是 类型擦除 http java sun com docs books tutorial ja
  • 无法为对象堆保留足够的空间

    每次尝试运行该程序时 我都会重复出现以下异常 VM初始化期间发生错误 无法为对象堆保留足够的空间 无法创建Java虚拟机 我尝试增加虚拟内存 页面大小 和 RAM 大小 但无济于事 我怎样才能消除这个错误 运行 JVM XX MaxHeap

随机推荐

  • DotNetZip知识系列:用来解压缩zip

    说明 这是 net平台可以使用的一个库 NuGet Gallery Package Downloads for DotNetZip 这是官方文档 About DotNetZip DotNetZip Documentation
  • 2022.03.06 mysql8拉链表-测试

    1 创建业务表并初始数据 drop table if exists mall user create table mall user uid bigint unsigned auto increment comment 用户唯一ID pri
  • shell快速迁移海量文件的两种方案

    最近遇到这样一个小需求 linux服务器上某个目录下有几百万个文件 导致各种操作不便 急需转移历史文件 保留90天 同时对转移到的目录下新建日期文件夹 按文件创建来存放文件 想到了两种解决方案 第一种直接按创建日期find 这样需检索整个目
  • 容器化部署dex适配openldap

    ldap LDAP 在OIDC流程中是用来做身份认证服务的 包括LDAP身份认证服务器 自己的第三方应用需要调用LDAP的客户端接口 用以访问LDAP服务器进行身份验证 作用 用户验证 用户管理 ldap它是用来做统一用户身份认证的 即 你
  • 电机磁链和反电势系数关系

    电机磁链和反电动势系数辨识 刚接触电机 不久 很容易就被绕晕了 磁链 空载相反电势幅值 电角频率 text 磁链 varphi frac text 空载相反电
  • img 显示response图片数据

    url http blog csdn net ykf69177 article details 8655881 url img src servlet IdentityServlet
  • 将分数阶工具箱FOMCON加入simulink中

    1 下载FOMCON toolbox压缩文件 网址为gitee下载地址 2 将下载的压缩文件放于安装matlab的文件夹 gt toolbox 并解压缩 3 添加路径 点击设置路径 添加文件夹 添加并包含子文件夹 点击保存 4 关闭matl
  • Linux基础命令-history历史记录

    Linux基础命令 alias设置别名 Linux学习中的博客 CSDN博客 文章目录 前言 一 history命令介绍 二 语法及参数 三 参考实例 总结 前言 在工作中 经常会需要多次重复某一个命令 或者需要查看之前执行过什么命令 那么
  • C/C++程序算法小练习--大整数减法

    大整数减法 include
  • 《软件测试》第10章 数据流测试

    本节是根据书籍 软件测试 Paul C Jorgensen著 中第十章的内容进行学习总结 更详尽的内容请查看作者原文 另在此也感谢原著作者的著文分享 本章主要内容如下
  • linux 安装jdk

    1 下载JDK jdk下载地址 http www oracle com technetwork java javase downloads jdk8 downloads 2133151 html 2 安装jdk 因为我安装的CentOS7
  • 项目实战二:关于element-ui前端框架自定义排序功能

    前言 近期 前端在开发的过程中 需要根据列表中字符串形式的数字进行升序或者降序排序 直接排序肯定是有问题的 这时就需要用到自定义排序的方式了 还有就是先将字符串的数字转化为Number类型的 具体代码如下 开启排序
  • blender建模常用建模快捷键

    编辑物体 M2选取 M2 SHIFT选取多个 A全选 B M1矩阵选择 C M1笔刷选择 CTRL M1套索选择 CTRL SHIFT M1取消套索选择 ALT M2选择边循环 面 CTRL ALT M2环边选择 线 CTRL 小键盘的 扩
  • 安卓移动应用开发之从零开始写安卓小程序2

    实验二 安卓文件的简介和我们的第一个安卓小程序 发布文章时没有保存 导致文章不对 在此抱歉 这次补上了 一 HelloWorld创建 1 File New NewProject 名字我们就写HelloWorld 其他都默认 包名可能会和我不
  • Spring Security入门

    1 Spring Security 简介 Spring Security 是一个高度可定制的身份验证和访问控制框架 它基于 Spring 框架 并可与 Spring 全家桶无缝集成 该框架可以精确控制用户对应用程序的访问 控制用户的角色和权
  • 二级路由dhcp关闭连不上wifi_手把手教你天翼校园网开wifi

    温馨提示 1 非广东海洋大学的学生或所用校园不是天翼校园网的童鞋可以酌情忽略本推文 2 为照顾小白 本文比较详细 请各位耐心阅读 天翼校园网大概是我见过最恶心的校园网了 表面说着是为了 保证上网环境安全 强制一号一终端 还不能开热点 实际上
  • Nginx配置origin限制跨域请求(应对等保)

    Nginx需要修复一个安全漏洞 这个需要根据客户端传递的请求头中的Origin值 进行安全的跨站策略配置 目的是对非法的origin直接返回403错误页面 配置如下 1 在http中定义一个通过map指令 定义跨域规则并返回是否合法 htt
  • python实现的jsencryp加密后端无法解密_python 3 实现js中JSEncrypt encrypt方法,rsa模块根据字符串公钥生成加密字符串...

    coding utf 8 import base64 import rsa all rsa encrypt def str2key s 对字符串解码 b str base64 b64decode s if len b str lt 162
  • qt控件学习(4)

    文章目录 QTabWidget 控件 QMenu QToolBar 控件 QSystemTrayIcon 任务栏控件 QTabWidget 控件 mainwindow h ifndef MAINWINDOW H define MAINWIN
  • 【JVM】内存管理

    目录 引言 1 内存分配 1 0 创建一个对象涉及的内存 1 1 方法区 1 2 堆 1 2 1 对象 堆里的存储单元 2 1 3 虚拟机栈 2 垃圾回收GC 2 1 垃圾回收的目标区域 2 2 垃圾回收算法 2 2 0 标记算法 2 2