内存分配与回收策略
大方向上讲,在堆上分配(也有可能被JIT编译过而导致在栈上分配),一般优先在eden上分配,如果开启了本地线程分配缓冲,将按线程在TLAB分配,也可能直接分配在老生代中。
没有绝对的规则,取决于JVM相关内存的参数设置和使用的垃圾收集器组合
对象优先在Eden分配,Eden没有足够的空间就会发生minor GC,即新生代GC,新生代一般是复制-清除算法,把活着的移到survivor区,如果survivor容纳不下,就会用老生代空间担保,移到老生代,如果空间担保不够,自然就要full gc,即老生代GC
PrintGCDetail打印各个代的详细垃圾收集信息,verbose:gc打印概略的垃圾收集信息
-Xms堆最小值 -Xmx堆最大值 如果相等意味着不能扩展 -Xmn新生代的大小
-XX:SurvivorRatio新生代中eden和一个survivor的比例
大对象直接进入老生代
大对象即需要大量连续内存空间的对象,典型的含有字节数组的对象。容易导致提前的GC因为需要连续空间。-XX:PretenureSizeThreshhold,如果对象大于这个值,直接进入老年代。有些GC收集器不支持这个参数。
长期存活的对象进入老生代
-XX:MaxtenuringThreshold
在eden创建后,经过第一次minor GC,能够存活并且能够被survivor包含的话,移动到survivor空间,age为1
然后在survivor中,每熬过一次minor GC,age就+1,如果大于max值就进入老生代
动态判断对象年龄,
如果survivor中的同一年龄的对象之和大于survivor空间一半的话,不用等到maxtenuringthreshold,大于或者等于这个年龄的对象都会进入老生代
空间担保
发生minorGC时,虚拟机会使用之前每次晋升到老生代的平均值和当前老生代剩余空间进行比较,如果大于则进行FULL gc,如果小于,则查看HandlePromotionFailure是否允许担保失败,如果不允许则进行full gc,如果允许则只进行minorgc,当实际情况导致担保失败时在进行一次full gc。通常为避免频繁full gc,还是应该将这个参数设置成允许