GC 日志及分析
实例:Roctetmq jvm 配置
JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn128m"
JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:SurvivorRatio=8"
JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:/home/jamin/gclogs/mq_gc_%p.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy"
......
GC 日志及分析
Java HotSpot(TM) 64-Bit Server VM (25.111-b14) for linux-amd64 JRE (1.8.0_111-b14), built on Sep 22 2016 16:14:03 by "java_re" with gcc 4.3.0 20080428 (Red Hat 4.3.0-8)
Memory: 4k page, physical 486008k(345116k free), swap 983036k(983036k free)
CommandLine flags: -XX:+AlwaysPreTouch -XX:G1HeapRegionSize=16777216 -XX:G1ReservePercent=25 -XX:GCLogFileSize=31457280 -XX:InitialHeapSize=268435456 -XX:InitiatingHeapOccupancyPercent=30 -XX:MaxDirectMemorySize=16106127360 -XX:MaxHeapSize=268435456 -XX:MaxNewSize=134217728 -XX:NewSize=134217728 -XX:NumberOfGCLogFiles=5 -XX:-OmitStackTraceInFastThrow -XX:+PrintAdaptiveSizePolicy -XX:+PrintGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:SoftRefLRUPolicyMSPerMB=0 -XX:SurvivorRatio=8 -XX:-UseBiasedLocking -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC -XX:+UseGCLogFileRotation -XX:-UseLargePages
----JVM 配置
0.061: [G1Ergonomics (Heap Sizing) expand the heap, requested expansion amount: 268435456 bytes, attempted expansion amount: 268435456 bytes]
2018-06-06T11:31:54.211-0400: 1.191: Total time for which application threads were stopped: 0.0000745 seconds, Stopping threads took: 0.0000133 seconds
2018-06-06T12:17:22.738-0400: 2729.717: [GC pause (G1 Evacuation Pause) (young) 2729.717: [G1Ergonomics (CSet Construction) start choosing CSet, _pending_cards: 543, predicted base time: 8.79 ms, remaining time: 191.21 ms, target pause time: 200.00 ms]
----2729.717 这个时间是GC 发生时间,jvm启动到GC 的秒数。GC pause (G1 Evacuation Pause) (young) 指出新生代minor GC 。
发生minor GC和full GC时,所有相关region都是要回收的。而发生并发GC时,会根据目标停顿时间动态选择部分垃圾对并多的Region回收,这一步就是选择要回收的Region。 _pending_cards是没有确定RSet的Card Table 数量。predicted base time是预测的扫描这些card table时间,后面说到目标停顿时间是 200ms
2729.717: [G1Ergonomics (CSet Construction) add young regions to CSet, eden: 7 regions, survivors: 1 regions, predicted young region time: 21.63 ms]
---- 添加young regions到 CSet(CSet(Collection Set) 收集集合。保存一次GC中即将进行GC的Region。占整个堆区的1%。) , eden 区有一个region , survivors 区有1个region
2729.717: [G1Ergonomics (CSet Construction) finish choosing CSet, eden: 7 regions, survivors: 1 regions, old: 0 regions, predicted pause time: 30.42 ms, target pause time: 200.00 ms]
---- young regions 添加到CSet 结果,后又提出了期望停顿时间和目标停顿时间
, 0.0081736 secs]
[Parallel Time: 7.6 ms, GC Workers: 1]
----一个线程进行回收,并行了 7.6ms
[GC Worker Start (ms): 2729717.5]
----GC 线程回收开始时间,jvm 启动到开始运行的时间。 可以看到和前面 2729.717 是一样的(多了0.5秒)
[Ext Root Scanning (ms): 1.4]
----扫描Roots花费的时间
[Update RS (ms): 0.8]
----Update RS (ms)是每个线程花费在更新Remembered Set上的时间。
[Processed Buffers: 17]
[Scan RS (ms): 0.0]
----扫描CSet中的region对应的RSet,因为RSet是points-into,所以这样实现避免了扫描old generadion region,但是会产生float garbage。
[Code Root Scanning (ms): 0.8]
----扫描code root耗时。code root指的是经过JIT编译后的代码里,引用了heap中的对象。引用关系保存在RSet中。
[Object Copy (ms): 4.5]
----拷贝活的对象到新region的耗时。
[Termination (ms): 0.0]
----当worker线程完成了自己那部分对象的复制和扫描,就进入终止协议。它查找未完成的工作(具体做了什么呢?), 一旦它完成就会再进入终止协议。
[Termination Attempts: 1]
----所有查找工作的尝试次数(attempts to steal work).
[GC Worker Other (ms): 0.0]
----每个GC线程中不能归属到之前列出的worker阶段的其他时间.
[GC Worker Total (ms): 7.5]
----GC总耗时
[GC Worker End (ms): 2729725.1]
----GC结束时间,相当于GC开始时间加上GC耗时
[Code Root Fixup: 0.3 ms]
----用来将code root修正到正确的 evacuate 之后的对象位置所花费的时间。
[Code Root Purge: 0.0 ms]
----清除code root的耗时,code root中的引用已经失效,不再指向Region中的对象,所以需要被清除。
[Clear CT: 0.0 ms]
----清除 RSet 扫描元数据(scanning meta-data)的 card table 消耗的时间.
[Other: 0.3 ms]
[Choose CSet: 0.0 ms]
---- 选定要进行垃圾回收的region集合时消耗的时间。通常很小,在必须选择 old 区时会稍微长一点点.
[Ref Proc: 0.1 ms]
----处理 soft, weak, 等引用所花费的时间,不同于前面的GC阶段
[Ref Enq: 0.0 ms]
----将 soft, weak, 等引用放置到待处理列表(pending list)花费的时间.
[Redirty Cards: 0.1 ms]
[Humongous Register: 0.0 ms]
[Humongous Reclaim: 0.0 ms]
[Free CSet: 0.0 ms]
[Eden: 112.0M(112.0M)->0.0B(112.0M) Survivors: 16.0M->16.0M Heap: 152.7M(256.0M)->38.9M(256.0M)]
---- Eden: 使用量(eden区总量)->回收后使用量(eden区总量) Survivors: 回收前使用量->回收后使用量 Heap: 回收前使用量(Heap总量)->回收后使用量(Heap总量),可以看出这个Heap 总量就是配置的量
[Times: user=0.01 sys=0.00, real=0.01 secs]
2018-06-06T12:23:42.174-0400: 3109.154: Total time for which application threads were stopped: 0.0422278 seconds, Stopping threads took: 0.0001244 seconds
控制参数:
-server
指定是server 模式
-XX:+UseG1GC
使用 G1 (Garbage First) 垃圾收集器
-XX:MaxGCPauseMillis=n
设置最大GC停顿时间(GC pause time)指标(target)。这是一个软性指标(soft goal), JVM 会尽量去达成这个目标.
-XX:+PrintGC
输出GC日志
-XX:+PrintGCDetails
输出GC的详细日志
-XX:+PrintGCTimeStamps
输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps
输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC
在进行GC的前后打印出堆的信息
-Xloggc:/home/jamin/logs/gc.log
日志文件的输出路径
-XX:+HeapDumpOnOutOfMemoryError
如果出现OutOfMemoryError 打印堆的快照
-XX:MaxTenuringThreshold=n
提升年老代的最大临界值(tenuring threshold). 默认值为 15.
-XX:ParallelGCThreads=n
设置垃圾收集器在并行阶段使用的线程数,默认值随JVM运行的平台不同而不同.
-XX:ConcGCThreads=n
并发垃圾收集器使用的线程数量. 默认值随JVM运行的平台不同而不同.
-XX:G1ReservePercent=n
设置堆内存保留为假天花板的总量,以降低提升失败的可能性. 默认值是 10.
-XX:G1HeapRegionSize=n
此参数可以指定每个region的大小. 默认值将根据 heap size 算出最优解. 最小值为 1Mb, 最大值为 32Mb.
-XX:G1NewSizePercent
新生代最小值,默认值5%
-XX:G1MaxNewSizePercent
新生代最大值,默认值60%
-XX:InitiatingHeapOccupancyPercent=n
启动并发GC周期时的堆内存占用百分比. G1垃圾收集器用它来触发并发GC周期,基于整个堆的使用率,而不只是某一代内存的使用比. 值为 0 则表示"一直执行GC循环". 默认值为 45.
-XX:+AlwaysPreTouch 系统不会真正分配内存给jvm,而是在使用的时候才分配,设置此参数后
JVM就会先访问所有分配给它的内存,让操作系统把内存真正的分配给JVM.后续JVM就可以顺畅的访问内存了。
-XX:GCLogFileSize=31457280
GC log 文件大小
-XX:+UseGCLogFileRotation
打开或关闭GC日志滚动记录功能,要求必须设置 -Xloggc参数
-XX:NumberOfGCLogFiles=5
设置滚动日志文件的个数,必须大于1。日志文件命名策略是,
.0, .1, ..., .n-1,其中n是该参数的值
-XX:InitialHeapSize=268435456
初始堆大小
-XX:MaxDirectMemorySize=16106127360
使用直接内存大小
-XX:MaxHeapSize=268435456
最大堆大小
-XX:MaxNewSize=134217728
新生代最大大小
-XX:NewSize=134217728
新生代初始大小
-XX:-OmitStackTraceInFastThrow
强制要求JVM始终抛出含堆栈的异常,编译优化后抛出的异常是没有堆栈信息的。(注意前面是 - 号)
-XX:+PrintAdaptiveSizePolicy
打印自适应收集的大小。默认关闭。
-XX:+PrintGCApplicationStoppedTime 打印gc一共停顿了多长时间。
-XX:SoftRefLRUPolicyMSPerMB=0
软连接对象并且可达,在最后一次被引用后将保持存活一段时间。默认值是堆中每空闲兆字节生存期的一秒钟
-XX:-UseBiasedLocking
禁用偏向锁(存在大量锁对象的创建并高度并发的环境下禁用偏向锁能够带来一定的性能优化)
-XX:LargePageSizeInBytes=10m
内存分页大小调整
-XX:-UseLargePages
启用大内存页支持(JDK是在1.5 update5以前的需要加这个参数)
-XX:+UseCompressedClassPointers
启用压缩类的指针
-XX:+UseCompressedOops
启用压缩普通对象指针(Oop=普通对象指针,64位机器指针会比32位占用的多,因为寻址更宽了)
可以让跑在64位平台下的JVM,不需要因为更宽的寻址,而付出Heap容量损失的代价。不过,它的实现方式是在机器码中植入压缩与解压指令,可能会给JVM增加额外的开销。
GC 日志分析工具
参考:https://blog.csdn.net/gzh0222/article/details/8223277