JVM运行原理和GC原理

一.新生代gc

新生代分成了Eden和2个Survivor,默认比例是8:1:1。 (-XX:SurvivorRatio=8)

当Eden内存存不下新对象时会触发Young GC;

Young GC会采用复制算法,从GC Roots(方法的局部变量、类的静态变量)开始追踪,标记出来存活的对象。然后把存活对象都放入在第一个Survivor区域s0中。接着垃圾回收器就会直接回收掉Eden区里剩余的全部垃圾对象,在整个这个垃圾回收的过程中全程会进入Stop the Wold状态,也就是暂停系统工作线程,系统代码全部停止运行,不允许创建新的对象。一旦垃圾回收全部完毕之后,也就是存活对象都进入了Survivor区域,然后Eden区都清空了,那么Young GC执行完毕,此时系统恢复工作,继续在Eden区里创建对象,下一次如果Eden区满了,就会再次触发Young GC,把Eden区和S0区里的存活对象转移到S1区里去,然后直接清空掉Eden区和S0区中的垃圾对象。

二.对象如何进入老年代

  1. 一个对象在年轻代里躲过15( -XX:MaxTenuringThreshold=15 默认)次垃圾回收,年龄太大了,寿终正寝,进入老年代
  2. 对象太大了,超过了一定的阈值,直接进入老年代,不走年轻代(-XX:PretenureSizeThreshold=<byte size>)
  3. 一次Young GC过后存活对象太多了,导致Survivor区域放不下了,这批对象会进入老年代。
  4. 可能几次Young GC过后,Surviovr区域中的对象占用了超过50%的内存,此时会判断如果年龄1+年龄2+年龄N的对象总和超过了Survivor区域的50%,此时年龄N以及之上的对象都进入老年代,这是动态年龄判定规则

老年代的回收推荐使用CMS,采用标记清理算法。

三.触发老年代的条件原因和造成的影响

        一旦老年代对象过多,就可能会触发Full GC,Full GC必然会带着Old GC,也就是针对老年代的GC,而且一般会跟着一次Young GC,也会触发永久代的GC。

1.老年代自身可以设置一个阈值,有一个JVM参数可以控制,一旦老年代内存使用达到这个阈值,就会触发Full GC,一般建议调节大一些,比如92%(-XX:CMSInitiatingOccupancyFraction=92);

2.在执行Young GC之前,如果判断发现老年代可用空间小于了历次Young GC后升入老年代的平均对象大小的话,那么就会在Young GC之前触发Full GC,先回收掉老年代一批对象,然后再执行Young GC。如果Young GC过后的存活对象太多,Survivor区域放不下,就要放入老年代,要是此时老年代也放不下,就会触发Full GC,回收老年代一批对象,再把这些年轻代的存活对象放入老年代中。

(JDK7和JDK7之前 如果-XX:-HandlePromotionFailure参数被打开了,当然一般都会打开,此时会进入第二步检查,就是看看老年代可用空间是否大于历次Minor GC过后进入老年代的对象的平均大小,大于则进行MinorGC,否则FullGC


触发Full GC几个比较核心的条件就是这几个,总结起来,其实就是老年代一旦快要搞满了,空间不够了,必然要垃圾回收一次。
Old GC的速度是很慢的,少则几百毫秒,多则几秒。所以一旦Full GC很频繁,就会导致系统性能很差,因为频繁要停止系统工作线程,导致系统看起来一直有卡顿的现象。
而且频繁Full GC还会导致机器CPU负载过高,导致机器性能下降,处理请求能力降低。
所以优化JVM的核心就是减少Full GC的频率。

四.正常情况下的gc情况

一般在几分钟一次Young GC,或者几十分钟一次Young GC,一次耗时在几毫秒到
几十毫秒的样子,都是正常的。
正常的Full GC频率在几十分钟一次,或者几个小时一次,这个范围内都是正常的,一次耗时应该在几百毫秒的样子。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值