JVM探秘:内存分配与回收策略
本系列笔记主要基于《深入理解Java虚拟机:JVM高级特性与最佳实践 第2版》,是这本书的读书笔记。
内存分配一般关注的是对象在堆上分配的情况,对象主要分配在新生代的Eden区中,如果启用了本地线程分配缓冲,将按线程优先在TLAB上分配。少数情况下也会直接分配在老年代中,这取决于使用的垃圾收集器组合,以及设置的JVM参数。
对象优先在Eden分配
大多数情况下,对象在Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机会发起一次Minor GC。
- Minor GC:发生在新生代的垃圾收集,因为一般大多对象具有朝生夕灭的特性,所以Minor GC发生非常频繁,回收速度也比较快。
- Major GC/Full GC:发生在老年代的垃圾收集,发生了Major GC,Major GC的回收速度比较慢。
当Minor GC时,发现Eden中已存在的对象,也无法放入Survivor区,那么就会通过分配担保机制提前转移到老年代。
大对象直接进入老年代
大对象一般是指需要大量连续内存空间的Java对象,最典型的大对象就是那种很长的字符串或数组,例如new byte[10 * 1024 * 1024]是一个10M的大对象。遇到大对象对虚拟机来说是可怕的,更可怕的是遇到一群朝生夕灭的短命大对象。经常遇到大对象,会导致在内存还有不少空间时就提前触发垃圾收集,用以获取足够的连续内存空间来安置大对象。
虚拟机提供了一个参数-XX:PretenureSizeThreshold,大于这个参数的对象会直接在老年代分配。这样能避免在Eden区和两个Survivor区之间大量的内存复制(新生代采用复制算法)。
长期存活的对象进入老年代
虚拟机采用了分代收集的思想来回收内存,既然这样,那内存回收时,虚拟机需要能识别哪些对象应该放到新生代,哪些对象应该放到老年代。为了做到这点,虚拟机给每个对象定义了一个对象年龄计数器。
如果对象在Eden区出生后经过一次Minor GC仍然存活,并且能被Survivor区容纳的话,那么对象将被移动到Survivor空间,同时对象年龄设为1。对象在Survivor区中每熬过一次Minor GC,对象年龄就增加1岁。当对象年龄达到一定值后(默认15),对象就会晋升到老年代中。这个晋升到老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshold设置。
动态对象年龄判定
有时为了适应不同的内存情况,虚拟机并不是死板的按照-XX:MaxTenuringThreshold的值,要求对象必须达到年龄阈值才能晋升老年代。
如果在Survivor空间中,所有相同年龄的对象的大小总和,大于Survivor空间的一半,那么年龄大于或等于该年龄的对象,都可以直接进入老年代,无须等到-XX:MaxTenuringThreshold设置的年龄阈值。
空间分配担保
新生代采用了复制收集算法,为了提高内存利用率,通常将新生代划分为了1个Eden区,和2个相同大小的Survivor区,它们的大小比例是8:1:1。这样其中的一个Survivor区来作为轮换备份,当出现大量对象在Minor GC后仍然存活时(极端情况例如所有对象都存活),Survivor区无法容纳,这时就需要老年代进行分配担保,将Survivor无法容纳的对象直接进入老年代。
老年代进行这样的分配担保,前提是老年代本身还有容纳这些对象的剩余空间。而有多少对象能存活下来在内存回收之前是无法准确预知的,所以只好根据之前每次回收晋升到老年代对象容量的平均大小,作为经验值,与老年代剩余空间进行比较。如果经验值大于剩余空间,这时老年代空间不足,就会发起一次Full GC。如果经验值小于剩余空间,就会Minor GC,这时新生代内存回收实际发生后,如果晋升到老年代时老年代空间不足,就会担保失败,担保失败则会再发起Full GC。
可见,担保失败后再Full GC,绕的圈子是最大的。按照现在分配担保的规则,只要老年代的连续空间大于新生代对象总大小,或历次晋升的平均大小,就会进行Minor GC,否则进行Full GC。
JVM探秘:内存分配与回收策略的更多相关文章
- JVM的内存分配垃圾回收策略
之前看过<深入了解Java虚拟机>感觉容易忘,今天写一篇博客加深一下印象. JVM的内存分配和垃圾回收(GC)主要发生在Java堆中.而Java堆根据对象的存活时间可以分为新生代和老年代, ...
- JVM的内存分配和回收策略
对象的Class加载 虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载.解析和初始化过.如果没有,那必须先执行相应 ...
- JVM:内存分配与回收策略
Java技术体系中所提倡的自动内存管理最终可以归结为自动化的解决了两个问题:给对象分配内存以及回收分配给对象的内存. 对象的内存分配,往大方向讲,就是在堆上分配(但也可能经过JIT编译后被拆散为标量类 ...
- jvm之内存分配与回收策略
1.java堆中各代分布 (1)Young:主要是用来存放新生的对象. (2)Old:主要存放应用程序中生命周期长的内存对象. (3)Permanent:是指内存的永久保存区域,主要存放Class和M ...
- Java虚拟机垃圾回收:内存分配与回收策略 方法区垃圾回收 以及 JVM垃圾回收的调优方法
在<Java对象在Java虚拟机中的创建过程>了解到对象创建的内存分配,在<Java内存区域 JVM运行时数据区>中了解到各数据区有些什么特点.以及相关参数的调整,在<J ...
- JVM垃圾回收器、内存分配与回收策略
新生代垃圾收集器 1. Serial收集器 serial收集器即串行收集器,是一个单线程收集器. 串行收集器在进行垃圾回收时只使用一个CPU或一条收集线程去完成垃圾回收工作,并且会暂停其他的工作线程( ...
- JVM学习十 -(复习)内存分配与回收策略
内存分配与回收策略 对象的内存分配,就是在堆上分配(也可能经过 JIT 编译后被拆散为标量类型并间接在栈上分配),对象主要分配在新生代的 Eden 区上,少数情况下可能直接分配在老年代,分配规则不固定 ...
- Java虚拟机内存分配与回收策略
内存分配与回收策略 Minor GC 和 Full GC Minor GC:发生在新生代上,因为新生代对象存活时间很短,因此 Minor GC 会频繁执行, 执行的速度一般也会比较快. Full GC ...
- jvm内存分配和回收策略
在上一篇中,已经介绍了内存结构是什么样的. 这篇来介绍一下 内存是怎么分配的,和怎么回收的.(基本取自<深入理解Java虚拟机>一书) java技术体系中所提倡的自动内存管理最终可以归结为 ...
随机推荐
- FastReport模板设计和调用
FastReport是功能齐全的报表控件,使开发者可以快速并高效地为·NET/VCL/COM/ActiveX应用程序添加报表支持.最近一个项目就涉及到了FastReport报表的应用.这里简单记录下( ...
- LOJ6079「2017 山东一轮集训 Day7」养猫
养ImmortalCO k可重区间问题 的增强版:有上下界! 直接都选择s[i],然后再把一些调整到e[i] 考虑通过最大流的“最大”,使得至少每k个有me个e, 通过最大流的“上界”,限制每k个最多 ...
- hdu 5745 La Vie en rose(2016多校第二场)
La Vie en rose Time Limit: 14000/7000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- H3C CSMA/CD冲突检测和退避
- jq杂项方法/工具方法----isArray()
https://www.cnblogs.com/sandraryan/ $.isArray()函数用于判断指定参数是否是一个数组.返回布尔值. <!DOCTYPE html> <ht ...
- C#循环语句练习(三)
for循环拥有两类:一.穷举:把所有可能的情况都走一遍,使用if条件筛选出来满足条件的情况. (1).羽毛球拍15元,球3元,水2元.200元每种至少一个,有多少可能. (2).百鸡百钱:公鸡2文钱一 ...
- Python--day21--复习
序列化模块总结: jison格式化输出: Serialize obj to a JSON formatted str.(字符串表示的json对象) Skipkeys:默认值是False,如果dict的 ...
- codeforces 1230 div2
C 给一个图,并且在边上放上多米诺骨牌,使得每个多米诺骨牌指向的顶点的数字是一致的,并且每种骨牌只能用一种.问最多能够覆盖多少条边. 先生成每一个点指向的数字,然后判断就好了. #include< ...
- Django使用cors解决跨域问题
1.安装Django-cors-headers模块 pip install django-cors-headers 2.配置settings.py文件 INSTALLED_APPS = [ ... ' ...
- HDU 6621"K-th Closest Distance"(二分+主席树)
传送门 •题意 有 $m$ 次询问,每次询问求 $n$ 个数中, $[L,R]$ 区间距 $p$ 第 $k$ 近的数与 $p$ 差值的绝对值: •题解 二分答案,假设当前二分的答案为 $x$,那么如何 ...