大对象直接进入老年代
然而实际在开发中,并不是所有对象都能这样进行GC流程。当对象过大时或特别大时,因为占用幸存者区空间过大或大于幸存者区,而造成反复GC,重复复制大对象增加GC时间问题,当然JVM对这方面有专门的优化。而这个机制就是
大对象直接进入老年代
,使用JVM参数-XX:PretenureSizeThreshold
(单位为字节)设置大对象的大小,如果对象超过设置的大小会直接进入老年代,防止大对象进入年轻代造成重复GC。
- 大对象
大对象就是需要大量连续内存空间的对象,即数组,字符串。
注意:该参数只在Serial和ParNew收集器才会生效,即Serial与ParNew存在该参数进行大对象区分。
补充: -XX:+UseSerialGC
采用Serial收集器
长期存活的对象将进入老年代
JVM采用分代收集来实现内存管理,就必须区分
不同对象进入不同代中进行不同
的处理,而JVM的解决方法是:给每一个对象设置对象头中的对象年龄计数器(Age)
对象流程:
- 经历过Minor GC,能够进入Survivor(幸存者区),则设置对象年龄为1
- 对象每经历过一次MinorGC,对象年龄就会加一
- 当年龄增加到达一定大小(默认15,CMS收集器默认6,其他不同的收集器会有所不同),将会进入老年代。
设置进入老年代年龄阈值:
-XX:MaxTenuringThreshold
对象动态年龄判断
在JVM中还有一种年龄判断机制:当一批对象的总大小大
大于
Survivor区域的50%,此时大于该批对象中的最大年龄的对象,直接进入老年代。
- 当minor gc后对象总和大于Survivor区域的50%,进行
- 该操作一般会在minor gc后进行触发
- 可以通过JVM参数
-XX:TargetSurvivorRatio
进行指定
该机制是为了使多次进行GC后还存在的对象更早进入老年代,至于为什么是大于50%Survivor区的对象,实际上Eden区和Survivor区中很少存在3,4次还幸存对象
其实就是一种根据经验来将迟早会进入老年代的对象提前进入
老年代空间分配担保机制
- 年轻代进行minor gc之前计算
老年代剩余可用空间
- 当年轻代在minor gc前所有的对象
大小之和
大于老年代剩余可用空间
时如果配置JVM参数
-XX:-HandlePromotionFailure
- 判断当前
老年代剩余可用空间
是否大于历史minor gc
后进入老年代的对象平均大小
- 当
老年代剩余可用空间
小于进入老年代对象的平均大小
或未设置时,将触发Full gc - 当
老年代剩余可用空间
大于进入老年代对象的平均大小
时,触发minor gc
,如果minor gc后存活并需要移动到老年代的对象总大小
还是大于老年代的可用空间,也将会触发Full gcFull gc对老年代和年轻代一起回收垃圾,诺Full gc后老年代的可用空间还是无法存放minor gc后需要进入老年代的对象,将会抛出
OOM
错误。
- 判断当前
- 否则进行Full gc即可,而小于则minor gc
该机制是为了尽可能的减少Full gc,并且哪怕无法避免full gc也可以在一定程度上减少年轻代对老年代的引用,加快了GC效率