阅读GC日志是处理java虚拟机内存问题的基础技能,每一种收集器的日志形式都是由它们自身的实现所决定的,换而言之,每个收集器的日志格式都不一样。但虚拟机设计者为了方便用户阅读,将各个收集器的日志都维持一定 的共性,例如以下两段典型的日志:
[GC (System.gc()) [PSYoungGen: 19712K->760K(38400K)] 19712K->768K(125952K), 0.0013102 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 760K->0K(38400K)] [ParOldGen: 8K->648K(87552K)] 768K->648K(125952K), [Metaspace: 3441K->3441K(1056768K)], 0.0063051 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
Heap
PSYoungGen total 38400K, used 333K [0x00000000d5c00000, 0x00000000d8680000, 0x0000000100000000)
eden space 33280K, 1% used [0x00000000d5c00000,0x00000000d5c534a8,0x00000000d7c80000)
from space 5120K, 0% used [0x00000000d7c80000,0x00000000d7c80000,0x00000000d8180000)
to space 5120K, 0% used [0x00000000d8180000,0x00000000d8180000,0x00000000d8680000)
ParOldGen total 87552K, used 648K [0x0000000081400000, 0x0000000086980000, 0x00000000d5c00000)
object space 87552K, 0% used [0x0000000081400000,0x00000000814a2368,0x0000000086980000)
Metaspace used 3447K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 376K, capacity 388K, committed 512K, reserved 1048576K
GC 日志开头的“[GC”
和“[Full GC”
说明了这次垃圾收集的停顿类型,而不是用来区 分新生代GC还是老年代GC的。如果有“Full”
,说明这次GC是发生了Stop-The-World的,例如下面这段新生代收集器ParNew的日志也会出现“[Full GC”(这一般是因为出现了分配 担保失败之类的问题 .所以才导致STW)。如果是调用System.gc()
方法所触发的收集,那么在这里将显示“[Full GC (System)”。
[Full GC 283.736: [ParNew: 261599K->261599K(261952K), 0.0000288 secs]
接下来的“[DefNew”、“[Tenured”、“[Perm”
表示GC发生的区域,这里显示的区域名称与使用的GC收集器是密切相关的,例如上面样例所使用的Serial收集器中的新生代名为“Default New Generation”
,所以显示的是“[DefNew”
。如果是ParNew
收集器,新生代名称就会变为 “[ParNew”
,意为 “Parallel New Generation”
。如果采用 Parallel Scavenge
收集器,那它配套的新生代称为“PSYoungGen”
,老年代和永久代同理,名称也是由收集器决定的。
后面方括号内部的19712K->760K(38400K)
含义是“GC前该内存区域已使用容量- >GC后该内存区域已使用容量 (该内存区域总容董)”。而在方括号之外的19712K->768K(125952K)
表示GC前Java堆已使用容量->表示GC后Java堆已使用容量(ava堆总容量)
再往后0.0063051 secs
表示该内存区域GC所占用的时间,单位是秒。[Times: user=0.01 sys=0.00, real=0.01 secs]
中的user sys real
分别代表用户态、内核态消耗的CPU事件和从开始到结束的墙种时间、和实际消耗量多少时间。墙种时间和CPU时间的区别是:墙种时间包括各种非运算时间的等待耗时如Io阻塞,而CPU时间不包括这些时间。
以下均以大小“10m”为例
-Xms10m:表示 Java 初始化堆的大小为10m
-Xmx10m:表示最大 Java 堆大小为10m
以上两个参数合用会限制java堆大小为10m,并且不可拓展
-Xss10m:表示每个 Java 线程堆栈大小为10m
-Xmn10m:为新生代的大小为10m
JVM的GC日志的主要参数包括如下几个:
-XX:SurvivorRatio=8 :决定了新生代中Eden和一个survivor区空间的比例为8:1
-XX:+PrintGC 输出GC日志
-XX:+PrintGCDetails 输出GC的详细日志
-XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2017-09-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息
-Xloggc:../logs/gc.log 日志文件的输出路径