读薄《深入理解 JAVA 虚拟机》Java内存分配策略

内存分配规则不是固定的,取决于当前使用的是哪一种垃圾收集器以及虚拟机配置。

对象优先在 Eden 上分配

大多数情况下,对象分配在 Eden 上,当内存不足的时候触发一次 Minor GC。

大对象分配进老年代

需要连续内存空间的对象,最典型的是很长的字符串已经数组,写程序的时候应该避免生命周期短的大对象。经常出现大对象内存不足以存放而提前出发 GC 的情况。

虚拟机提供了一个参数 -XX:PretenureSizeThreshold 参数,当大于这个参数设置值的对象的时候直接在老年代分配。

长期存活对象进入老年代

虚拟机给每一个对象都有一个年龄计数器,当每一次 GC 后,被保留下来的对象的年龄就加一。

当年龄达到一定程度,就会晋升到老年代。

可以通过参数 -XX:MaxTenuringThreshold 来设置晋升老年代的阈值。

动态对象年龄判定

为了更好适应虚拟机环境,如果在 survivor 空间中所有相同年龄对象总和大于 Survivor 空间一半,则这些对象都直接进入老年代。

空间担保分配

当发生 Minor GC 之前,虚拟机会检查老年代最大可用空间是否大于新生代所有的对象的空间,如果大于,则这次 GC 是安全的,直接进行 GC。如果小于,则会去查看 HandlePromotionFailure 设置值是否允许担保失败。如果允许,则会去查看最近 GC 完对象剩余平均值,如果剩余平均值小于老年代可以用来担保的空间,则进行一次有风险的 Minor GC。否则就进行一次 Full GC。

如果不允许冒险,则直接进行 Full GC。

但是这个参数在 JDK 24 后就不再使用,如果老年代大于平均值则直接 Minor GC。

猜你喜欢

转载自www.cnblogs.com/stonymoon/p/9911697.html