JVM调优学习之旅-(4)G1
G1垃圾回收器介绍
G1垃圾回收器在我们设置堆内存大小后,JVM启动在默认情况下把堆内存拆分为大小均等的region具体大小是—堆内存/2048。region大小是2的倍数。
可以通过 “-XX:G1HeapRegionSize” 设置region大小。
region 数量是动态的。初始的时候新生代region只有5%,会随着新生代增加region跟着增加。 垃圾回收后也会减少。默认新生代的占比不会超过60%,可以通过**“- XX:G1MaxNewSizePercent”**设置
新生代
新生代也是有eden区 s1,s2 的区别的他们的数量也是根据region的增加而增加,也是根据一定比例来决定的。“-XX:SurvivorRatio=8”
什么时候进入老年代
- 当年龄到了会进入老年代,年龄设置**“-XX:MaxTenuringThreshold”** 默认15
- 动态年龄规划或某一次发生GC后存货对象大于s区一半。
大对象去哪了
G1 会有专门的region 存放大对象,甚至一个大对象可以放几个region。由于新生代region是逐渐变大,所以大对象是在还没分配新生代的时候,region 就是用来存放大对象的。新生代 老年代GC 都会来回收大对象。
G1垃圾回收的过程
- 初始标记:先STW,然后对各个线程栈内存中的局部变量代表的GC Roots,以及方法区中的类静态变量代表的GC Roots,进行扫描,标记出来他们直接引用的那些对象。
- 并发标记:通过gc roots 追踪全部对象。并且会标记在这期间有哪些对象修改。(比如说哪个对象被新建了,哪个对象失去了引用)
- 最终标记阶段:先STW,但是会根据并发标记 阶段记录的 那些对象修改,最终标记一下有哪些存活对象,有哪些是垃圾对象。
- 混合回收阶段:会STW,这个阶段会计算老年代中每个Region中的存活对象数量,存活对象的占比,还有执行垃圾回 收的预期性能和效率。然后在限定的时间范围内尽可能回收对象。会选择部分Region进行回收,因为必须让垃圾回收的停顿时间控制在我 们指定的范围内。
|
|
什么时候自动触发新生代+老年代的混合垃圾回收
G1有一个参数,是“-XX:InitiatingHeapOccupancyPercent”,他的默认值是45%;当老年代占据堆内存45% 就会尝试触发一个新生代+老年代一起回收的混合回收阶段。 又称Mixed GC
混合回收过程
由于混合回收由于停顿时间的原因,会有多次。有一些参数可以控制这个,比如**“-XX:G1MixedGCCountTarget”**参数,就是在一次混合回收的过程中,最后一个阶段执行几次混合 回收,默认值是8次
因为你停止系统一会儿,回收掉一些Region,再让系统运行一会儿,然后再次停止系统一会儿,再次回收掉一些Region,这样可以尽 可能让系统不要停顿时间过长,可以在多次回收的间隙,也运行一下。
还有一个参数,就是**“-XX:G1HeapWastePercent”**,默认值是5% 他的意思就是说,在混合回收的时候,对Region回收都是基于复制算法进行的,都是把要回收的Region里的存活对象放入其他 Region,然后这个Region中的垃圾对象全部清理掉。一旦空闲出来的Region数量达到了堆内存的5%,此时就会 立即停止混合回收,意味着本次混合回收就结束了。
而且从这里也能看出来G1整体是基于复制算法进行Region垃圾回收的,不会出现内存碎片的问题,不需要像CMS那样标记-清理之 后,再进行内存碎片的整理。
还有一个参数,“-XX:G1MixedGCLiveThresholdPercent”,他的默认值是85%,意思就是确定要回收的Region的时候,必须是存 活对象低于85%的Region才可以进行回收 否则要是一个Region的存活对象多余85%,你还回收他干什么?这个时候要把85%的对象都拷贝到别的Region,这个成本是很高的。
回收失败
由于是给予复制算法进行回收,那么再拷贝的过程发现存活的对象没有地方放得下,那么会触发失败,会停止系统程序,然后采用单线程标记算法来回收。很慢。
从上面可以看出G1非常适合大内存的系统和延时要求较小的系统,例如实时通信,因为parnew垃圾回收器如果是大内存的话,在垃圾回收期间,会有很长的停顿时间,而G1可以控制每次回收停顿时间。
G1垃圾回收模拟分析
|
|
我们采用G1垃圾回收器
|
|
在G1垃圾回收器中有一个至关重要的参数会影响到GC的表现,就是“-XX:MaxGCPauseMills”,他的默认值是200 毫秒
也就是说咱们希望每次触发一次GC的时候导致的系统停顿时间(也就是“Stop the World”)不要超过200毫秒,避 免系统因为GC长时间卡死。
分析
G1会根据停顿时间的长度来估算回收时间,意思就是
|
|
停顿时间到底应该怎么设置
|
|
所以这个参数到底如何设置,需要结合后续给大家讲解的系统压测工具、gc日志、内存分析工具结合起来进行考虑,尽量让系统的gc频率别太高,同时每次gc停顿时间也别太长,达到一个理想的合理值
G1与parnew+cms的区别点
|
|
parallel scavenge与 parnew两者都是复制算法,都是并行处理,但是不同的是,parallel scavenge 可以设置最大gc停顿时间(-XX:MaxGCPauseMills)以及gc时间占比(-XX:GCTimeRatio)
parallel scavenge更关注 吞吐量 ,不过目前系统喜欢吞吐量的基本都用G1了。
G1也可以做到 parallel scavenge+Parallel Old的功能