美文网首页
常用垃圾回收器及JVM参数

常用垃圾回收器及JVM参数

作者: 不是明天 | 来源:发表于2019-04-10 14:54 被阅读0次

    一.垃圾回收相关参数

    1.-XX:+PrintGC

    每次young GC或full GC打印简单日志信息,默认输出到终端

    [GC (Allocation Failure)  72286K->7246K(251392K), 0.0081499 secs]
    [GC (Metadata GC Threshold)  70587K->8922K(251392K), 0.0086172 secs]
    [Full GC (Metadata GC Threshold)  8922K->8549K(251392K), 0.0367123 secs]
    

    格式:[GC类型] 清理前堆使用量->清理后堆使用量(当前堆大小),清理的时间

    该参数不能打印详细的GC日志,比如判断是否对象从年轻代转移老年代。

    2.-XX:PrintGCDetails

    详细的GC日志,一般选择开启。日志格式与选择的垃圾收集器有关。
    

    同时使用PrintGC和PrintGCDetails,只会显示PrintGCDetails。

    以下是使用PS垃圾收集器的PrintGCDetails young GC日志:

    [GC (Allocation Failure) [PSYoungGen: 65536K->6747K(76288K)] 65536K->6755K(251392K), 0.0116237 secs] [Times: user=0.01 sys=0.00, real=0.02 secs] 
    

    通过以上发现:
    年轻代在young GC中堆空间从65536K减到6747K,用时0.0116237 secs,使用的垃圾收集器是PS(Parallel Scavenge GC);JVM堆使用量从65536K降到6755K,总大小为251392K。同时打印消耗时间。

    是否可以计算出有6755K-6747K的内存进入老年代?

    以下是使用PS垃圾收集器的PrintGCDetails old GC日志:

    [Full GC (Metadata GC Threshold) [PSYoungGen: 8838K->0K(76288K)] [ParOldGen: 88K->8621K(175104K)] 8926K->8621K(251392K), [Metaspace: 20551K->20551K(1067008K)], 0.0494903 secs] [Times: user=0.10 sys=0.01, real=0.05 secs] 
    

    以上各参数与young GC一致,注意user=0.10 sys=0.01, real=0.05 secs,说明使用了多线程。

    3.XX:+PrintGCTimeStamps和-XX:+PrintGCDateStamps

    -XX:+PrintGCTimeStamps:GC时打印jvm启动至今的时间戳
    -XX:+PrintGCDateStamps: GC时打印jvm启动至今的绝对日期和时间

    4.-Xloggc

    -Xloggc:也可以输出到指定的文件(-Xloggc:./log/gc.log)

    这个参数隐式的设置了参数-XX:+PrintGC和-XX:+PrintGCTimeStamps,但建议显示指定。

    二、具体的垃圾收集器分析

    1.一般的虚拟机参数:

    -Xmx256m -Xms256m  -Dfile.encoding=UTF-8 -Dserver.port=8010 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/dump  -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCDateStamps  -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
    

    2.ParNew和CMS GC

    ParNew:Serial收集器的多线程版本,基于“复制算法”;

    为什么选择ParNew?
    运行在Server模式下的虚拟机中首选的新生代收集器,其中一个与性能无关但很重要的原因是,除了Serial收集器外,目前只有它能与CMS收集器配合工作。

    CMS(Concurrent Mark Sweep):以获取最短回收停顿时间为目的的收集器,基于“标记-清除”算法。

    为什么选择CMS?
    因为是多核处理器,并发收集、低停顿,适合web服务端应用。

    3.Full/Major GC

    Major GC :清理老年代
    Full GC :清理整个堆空间—包括年轻代和老年代。

    4.CMS垃圾收集过程:

    初始标记

    作用:标记老年代中所有的GC ROOT,标记被年轻代中活着的对象引用的对象。
    会stop-the-world。

    收集阶段,开始收集所有的GC Roots和直接引用到的对象

    2019-04-09T16:20:55.865-0800: [GC (CMS Initial Mark) [1 CMS-initial-mark: 17539K(174784K)] 26422K(253440K), 0.0034858 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
    

    格式:[老年代使用容量(新生代使用容量)]堆使用量(堆容量),时间计量

    并发标记

    作用:从GC root开始,遍历老年代标记所有存活的对象,与应用线程并发运行。

    2019-04-09T16:20:55.869-0800: [CMS-concurrent-mark-start]
    2019-04-09T16:20:55.894-0800: [CMS-concurrent-mark: 0.025/0.025 secs] [Times: user=0.05 sys=0.01, real=0.03 secs]  
    

    这里停顿了0.03秒

    并发预清理

    作用:并发标记在前一个阶段改变了的对象(Dirty Card),能够从dirty card对象到达的对象也会被标记。

    2019-04-09T16:20:55.894-0800: [CMS-concurrent-preclean-start]
    2019-04-09T16:20:55.895-0800: [CMS-concurrent-preclean: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    

    可终止的并发预清理

    这个阶段尝试着去承担STW的Final Remark阶段足够多的工作,很大程度的影响着即将来临的Final Remark的停顿。

    
    2019-04-09T16:21:29.403-0800: [CMS-concurrent-abortable-preclean-start]
    2019-04-09T16:21:34.456-0800: [CMS-concurrent-abortable-preclean: 1.684/5.053 secs] [Times: user=2.05 sys=0.04, real=5.05 secs]
    
    

    重新标记

    这个阶段是CMS中第二个并且是最后一个STW的阶段。该阶段的任务是完成标记整个年老代的所有的存活对象

    2019-04-09T16:20:55.895-0800: [GC (CMS Final Remark) [YG occupancy: 8882 K (78656 K)]2019-04-09T16:20:55.895-0800: [Rescan (parallel) , 0.0031235 secs]2019-04-09T16:20:55.898-0800: [weak refs processing, 0.0005258 secs]2019-04-09T16:20:55.899-0800: [class unloading, 0.0041574 secs]2019-04-09T16:20:55.903-0800: [scrub symbol table, 0.0070362 secs]2019-04-09T16:20:55.910-0800: [scrub string table, 0.0005311 secs][1 CMS-remark: 17539K(174784K)] 26422K(253440K), 0.0157999 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
    

    并发清除

    和应用线程同时进行,不需要STW。这个阶段的目的就是移除那些不用的对象,回收他们占用的空间并且为将来使用。

    2019-04-09T16:20:55.911-0800: [CMS-concurrent-sweep-start]
    2019-04-09T16:20:55.920-0800: [CMS-concurrent-sweep: 0.009/0.009 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
    

    并发重置

    这个阶段并发执行,重新设置CMS算法内部的数据结构,准备下一个CMS生命周期的使用。

    2019-04-09T16:20:55.920-0800: [CMS-concurrent-reset-start]
    2019-04-09T16:20:55.920-0800: [CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    

    5.触发GC的时机:

    Minor GC触发条件:当Eden区满时,触发Minor GC。
    Full GC触发条件:

    (1)调用System.gc时。

    系统建议执行Full GC,但是不必然执行

    (2)老年代空间不足

    由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

    (3)promotion failed

    promotion failed是在进行Minor GC时,survivor space放不下、对象只能放入老年代,而此时老年代也放不下造成的

    (4)统计得到的Minor GC晋升到旧生代的平均大小大于老年代的剩余空间
    这是一个较为复杂的触发情况,Hotspot为了避免由于新生代对象晋升到旧生代导致旧生代空间不足的现象,在进行Minor GC时,做了一个判断,如果之前统计所得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间,那么就直接触发Full GC。

    (6)堆中分配很大的对象
    所谓大对象,是指需要大量连续内存空间的java对象,例如很长的数组,此种对象会直接进入老年代,而老年代虽然有很大的剩余空间,但是无法找到足够大的连续空间来分配给当前对象,此种情况就会触发JVM进行Full GC。

    参考:
    https://blog.csdn.net/chenleixing/article/details/46706039
    https://blog.csdn.net/f59130/article/details/74013460

    相关文章

      网友评论

          本文标题:常用垃圾回收器及JVM参数

          本文链接:https://www.haomeiwen.com/subject/cawniqtx.html