JVM----对象怎么到的老年代

1.什么是Minor GC

JVM堆内存主要分为新生代和老年代,Minor GC就是回收新年带的GC,也称为Young GC,老年代的GC 就是 Full GC。

新生代又分为Eden区和两个Servivor区,这个在下面的时候可能会用到。(两个Servivor区就简称为S1区和S2区)

2.躲过15次的GC之后进入老年代

每次对象新生成的时候,会在Eden区生成,如果Eden区满了,就会发生一次Minor GC,这个时候会把Eden区还存活的对象复制到S1区,这个时候从Eden区到S1去的对象,他们的年龄就开始计数了,等下次发生Minor GC的时候S1存活的对象会复制到S2区,这个时候存活的对象的年龄就会加1,这样躲过15次之后的对象会把这样的对象放到老年代。

那么这个15次是不是可以修改的?这个肯定是可以修改的,我们可以使用-XX:MaxTenuringThreshold来设置多少次之后会进入老年代,默认是15次。

那么我们可以把这个对象设置成很大很大么?这肯定是不行的,这个值最大就是15。

为什么最大是15呢?这个就需要去看看对象头的信息了,在对象头里面有个存储GC次数的位置,JVM预留了4个字节来存储,所以4个字节做大的15了,当然了,我前几年也看到过说可以设置更大的,但是我现在觉得这个值要是改的话,并没有想象中的那么好改。

3.动态年龄判断

如果咱们S1区的大小就100M,这样的话如果每次Minor GC都会产生30M的存活会比较久的对象,这个时候,可能进行了4次Minor GC之后S区就满了,所以这里JVM做了一些优化。

当Minor GC之后,S区存活的对象大小,大于50%的时候会把部分对象直接复制到老年代。

那怎么判断哪些对象需要到老年代的呢?年龄1+年龄2+年龄N的对个年龄的总和超过了S1区的50%,这个时候就会把大于等于年龄N的对象都放入老年代。

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

在JVM参数里面,-XX:PretenureSizeThreshold就是,当一个对象的大小超过多少的时候,就可以直接把该对象直接放入老年代,不用经过S区。

这个就非常好理解了,如果大对象频繁的出现在S区,会把一些应该回收的一些小对象直接进入到老年代。

这个也是我们在做JVM优化的时候需要考虑的一个点,希望在以后的工作中,如果遇到这样的问题,不会不知道。

5.Eden区直接到老年代

在什么情况下Eden区的存活对象会直接到老年代呢?

当Minor GC之后发现剩余的存活对象太多了,没有办法放入带另外一块S区的时候,JVM会把这些对象直接放入到老年代中。

6.老年代空间分配担保

这个说起来可能就有点早了,在JDK 6 Update 24之前,在发生Minor GC之前,虚拟机必须先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那这一次Minor GC可以确保是安全的。如果不成立,则虚拟机会先查看-XX:HandlePromotionFailure参数的设置值是否允许担保失败(HandlePromotion Failure);如果允许,那会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试进行一次Minor GC,尽管这次Minor GC是有风险的;如果小于,或者-XX:HandlePromotionFailure设置不允许冒险,那这时就要改为进行一次FullGC。

在JDK 6 Update 24之后不再使用-XX:HandlePromotionFailure参数了,JDK 6 Update 24之后的规则变为只要老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小,就会进行Minor GC,否则将进行Full GC。

这个大家记下来就好了,可能在未来的面试的时候可能会问到。

7.总结

其实没什么可以总结的地方,明白了这些对象是怎么进入到的老年代,我们在以后优化的时候,就可以判断是不是有我们设置不太对的地方,然后去调整。

可以根据GC的日志看到在什么时候什么发生的GC,根据对应区域的变化来对线上的系统进行一些优化。

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值