jvm

JVM 系列 内存分配与回收策略

开启JVM探索新篇章

Posted by lichao modified on November 7, 2019

对象 优先在eden分配

大多数情况下,对象在eden区中分配。当eden区没有足够空间进行分配时,虚拟机将发起一次minor GC。

大对象直接进入老年代

虚拟机提供一个参数(-XX:PretenureSizeThreshold),令大于这个设置值的对象直接在老年代分配。这样做的目的是避免在eden区及两个survivor区之间发生大量的内存复制。

大对象:需要大量连续内存空间的Java对象,最典型的大对象就是那种很长的字符串以及数组。经常出现大对象容易导致内存还有不少空间时就提前触发垃圾收集以获得足够的连续空间来安置它们。

长期存活的对象进入老年代

虚拟机 给 每个对象定义了一个对象年龄的计数器。如果对象在 eden 出生并经过第一次 minorGC 后仍然存活,并且能被survivor 容纳的话,将被移动到 survivor 空间中,并且对象年龄设置为 1。对象在 survivor 区中每熬过一次minorGC,年龄就增加 1 岁,当它的年龄增加到一定程度(默认为15岁),就将会被晋升到老年代中。

动态对象年龄判断

如果在 survivor 空间中相同年龄所有对象大小的总和大于 survivor 空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无需保证年龄阈值。

空间分配担保

在发生 minorGC 之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间。如果这个条件成立,那么 minorGC 可以确保是安全的。

如果不成立,在虚拟机允许担保失败的情况下,则虚拟机 会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次minorGC,尽管这次minorGC是有风险的。

如果出现担保失败,会在失败后重新发起一次FullGC,

如果小于,或者虚拟机允许不担保失败,那这时需要进行进行一次full GC