第三章:内存分配与回收策略

Java内存自动管理可以解决两个问题:给对象分配内存和回收分配给对象的内存;
给对象分配内存,都是在堆上进行分配的, 对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓存TLAB,将按线程优先在TLAB上分配,少数情况也可能会直接分配在老年代中,分配的规则并不是固定的,也取决于当前使用的垃圾回收器组合。
  • 大对象直接在老年单分配:需要大量连续存储空间的Java对象,典型的大对象就是长的字符串或者数组。可以通过设置-XX:PretenureSizeThreshold参数,令大于这个值的对象直接在老年代中分配内存,这样做的好处避免了在新生代中复制大量的内存(Eden与Survior)。
-XX:PretenureSizeThreshold参数只对Serial和ParNew两种回收器有效。
Parallel Scavenger回收器一般不需要设置-XX:PretenureSizeThreshold参数。
  • 长期存活的对象进入老年代中,为了做到这一点,需要在每个对象头上记录对象年龄(即对象在新生代中经过了几次复制),默认当对象头中age大于15时,会把对象放到老年代中,可以通过-XX:MaxTenuringThreshold设置。
  • 动态对象年龄判定:虚拟机中并不是一定按照每个对象头中age来判定对象是否进入老年代的,如果在Survior空间中相同年龄所有对象大小的总和大于Survior空间的一半,年龄大于或者等于该年龄的对象就可以直接进入老年代中,无需等待MaxTenuringThreshold中要求的年龄。
  • 空间担保:在发生Minor GC之前,会检测老年代中最大连续内存空间是否大于新生代中多有对象总空间,如果这个条件成立,那么Minor GC是安全,因为如果新生代中所有对象都放入老年代中是可以存放下。如果这个条件不成立,则检查HandlePromotionFailure设置值是否允许担保失败,如果允许,那么继续检查老年代最大可用的连续内存是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试进行一次Minor GC,尽管Minor GC有风险,如果小于或者HandlePromotionFailure设置不允许风险,这时将进行一次Full GC。

猜你喜欢

转载自www.cnblogs.com/use-D/p/10727129.html