通过-XX:+PrintGC
或-XX:+PringGCDetails
参数可以打印出简略的或详细的GC日志。
JVM的GC有两种:Minor GC
和Full GC
Minor GC日志: 一个示例:
[GC [PSYoungGen: 3264K->0K(3328K)] 3576K->312K(10176K), 0.0001356 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
复制代码
我觉得吧,把日志缩进显示容易看一点:
[GC // 表示是minor GC,即对新生代进行垃圾回收
[PSYoungGen: // PS:垃圾回收器,Parallel Scavenge;YoungGen:新生代
3264K->0K(3328K) // 新生代内存变化情况。gc前->gc后(总内存)
]
3576K->312K(10176K), // 堆内存变化情况。gc前->gc后(总内存)
0.0001356 secs // 新生代垃圾回收耗时
]
[Times:
user=0.00 // 用户耗时
sys=0.00, // 系统耗时
real=0.00 secs // 实际耗时
]
复制代码
上面的PSYoungGen可以看出垃圾回收发生在新生代的,用的是Parallel GC垃圾回收器,相关参数:-XX:+UseParallelGC
Full GC日志: 一个示例:
[Full GC (Metadata GC Threshold) [PSYoungGen: 7677K->0K(103936K)] [ParOldGen: 5847K->13176K(71168K)] 13525K->13176K(175104K), [Metaspace: 20580K->20580K(1067008K)], 0.0551431 secs] [Times: user=0.14 sys=0.00, real=0.05 secs]
复制代码
缩进:
[Full GC (Metadata GC Threshold) // Full GC(gc的原因,由于Metaspace区域内存达到了阈值触发full gc)
[PSYoungGen: // 新生代GC
7677K->0K(103936K) // 新生代内存变化情况。gc前->gc后(总内存),减少7677K
]
[ParOldGen: // 老年代GC
5847K->13176K(71168K) // 老年代内存变化情况。gc前->gc后(总内存),增加7329K
]
13525K->13176K(175104K), // 堆内存变化情况。gc前->gc后(总内存),
// 13525-13176=减少了349K,而上面-7677+7329=减少了348K,数据基本吻合
[Metaspace:
20580K->20580K(1067008K) // 元数据区内存变化情况。gc前->gc后(总内存),
], 0.0551431 secs // 整个GC过程耗时
]
[Times: user=0.14 sys=0.00, real=0.05 secs]
复制代码
上面的ParOldGen可以看出垃圾回收发生在老年代的,用的是一个并行的标记清除压缩垃圾回收器
ParOldGen – Type of the collector used to clean the Old Generation. In this case, parallel mark-sweep-compact stop-the-world garbage collector named ParOldGen was used.
By default class metadata allocation is only limited by the amount of available native memory. We can use the new option MaxMetaspaceSize to limit the amount of native memory used for the class metadata. It is analogous to MaxPermSize. A garbage collection is induced to collect the dead classloaders and classes when the class metadata usage reaches MetaspaceSize (12Mbytes on the 32bit client VM and 16Mbytes on the 32bit server VM with larger sizes on the 64bit VMs). Set MetaspaceSize to a higher value to delay the induced garbage collections. After an induced garbage collection, the class metadata usage needed to induce the next garbage collection may be increased.
Full GC还会在程序退出前打印下面的信息:
Heap
PSYoungGen total 3328K, used 69K [0x000000000b580000, 0x000000000b8d0000, 0x000000000b8d0000) //Line1
eden space 3264K, 2% used [0x000000000b580000,0x000000000b591688,0x000000000b8b0000)
from space 64K, 0% used [0x000000000b8b0000,0x000000000b8b0000,0x000000000b8c0000)
to space 64K, 0% used [0x000000000b8c0000,0x000000000b8c0000,0x000000000b8d0000)
PSOldGen total 6848K, used 312K [0x000000000aed0000, 0x000000000b580000, 0x000000000b580000) //Line2
object space 6848K, 4% used [0x000000000aed0000,0x000000000af1e0c0,0x000000000b580000)
PSPermGen total 21248K, used 3817K [0x0000000005ad0000, 0x0000000006f90000, 0x000000000aed0000) //Line3
object space 21248K, 17% used [0x0000000005ad0000,0x0000000005e8a4a0,0x0000000006f90000)
复制代码
Line1解析:
PSYoungGen //新生代
total 3328K, //总大小
used 69K //已使用
[0x000000000b580000, //16进制数,表示新生代下界
0x000000000b8d0000, //新生代当前上届
0x000000000b8d0000) //新生代上届
复制代码
新生代空间最大值 = 上界 - 下界 = 0x000000000b8d0000 - 0x000000000b580000
= 350000(16进制)
= 3473408(10进制)
= 3473408 / 1024 = 3392K
3392K刚好等于下面 eden + from + to的大小。
当前已分配的新生代空间大小 = 当前上界 - 下界 = 3392K
复制代码
Line2: 老年代的内存情况
Line3: 永久代的内存情况
参考文章: GC日志分析