JVM中对象进入老年代的3种情况

1. 对象年龄达到阈值后进入老年代

默认情况下,对象在新生代经历了15次GC后,便会达到进入老年代的条件,将对象转移进入老年代。当然,年龄的阈值可以通过JVM参数进行设置:

-XX:MaxTenuringThreshold=10

2. 大对象直接进入老年代

通过以下JVM参数进行设置:(注意此参数仅适用于Serial和ParNew两款新生代收集器。)

-XX:PretenureSizeThreshold=5242880

其中5242880即为5MB(5*1024*1024),意味着对象大于5MB直接进入老年代

public void test(){
    byte[] array=new byte[6*1024*1024];
}

原因:

a. 大对象需要连续的内存空间,而新生代为了安放大对象可能需要多次进行GC,增加开销;

b. 新生代种伊甸园区和幸存者区常采用复制算法,需要经常复制对象到不同的区域,而大对象在复制时开销较大。

3. 动态地根据对象地年龄以及新生代空间使用情况选择对象进入老年代

HotSpot虚拟机并不一定会严格按照设置的年龄阈值,满足以下条件也能直接进入老年代:Survivor 区中,年龄从 1 到 n 的对象大小之和超过 Survivor 区的 50% 时,新生代中年龄大于等于 n 的对象将进入老年代。

注意一个误区:这个对象大小总和是按年龄从小到大累加的,并不是同龄对象!

在《深入理解java虚拟机》这本书中是这样说的:

如果在Survivor空间中相同年龄所有对象大小的总和大于 Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到-XX: MaxTenuringThreshold中要求的年龄。

但如果是同龄对象,那么意味着假设对象年龄为1,超过一半就得把所有对象放进老年代,且再分析一下,随着Minor GC,对象年龄只会越来越大,同龄对象只会越来越少,意味着若是同龄对象,那么对象年龄只能为1。

又或者是假设 Survivor 区中对象年龄各不同,如果是同龄对象而不是从小累加的话,那么老年代始终为空,Survivor 区始终是满的,不符合正常现象。

另外,这个50%也是可以通过参数设置的:(默认50%)

-XX:TargetSurvivorRatio

你可能感兴趣的:(jvm,java,开发语言)