有些参考的连接
垃圾收集器简介
实用JVM参数总结
JVM 常见参数设置和分析
理解GC日志是处理JAVA虚拟机内存问题的基础技能,它只是一些人为确定的规则,没有太多的技术含量,每种收集器的日志形式都是由他们自身的实现所决定的,不同的收集器的日志格式也不一样。
下面是一个GC的日志
(1)Java HotSpot(TM) 64-Bit Server VM warning: ignoring option HandlePromotionFailure; support was removed in 6.0_24
(2)2018-05-05T22:34:16.800+0800: [GC [PSYoungGen: 8184K->1000K(9216K)] 8184K->3398K(19456K), 0.0080798 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
(3)2018-05-05T22:34:16.808+0800: [GC [PSYoungGen: 7445K->952K(9216K)] 9843K->9502K(19456K), 0.0042325 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
(4)2018-05-05T22:34:16.813+0800: [Full GC [PSYoungGen: 952K->0K(9216K)] [ParOldGen: 8550K->7001K(10240K)] 9502K->7001K(19456K) [PSPermGen: 4940K->4939K(21504K)], 0.0267644 secs] [Times: user=0.02 sys=0.00, real=0.03 secs]
(5)Heap
(6) PSYoungGen total 9216K, used 6234K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
(7) eden space 8192K, 76% used [0x00000000ff600000,0x00000000ffc16b08,0x00000000ffe00000)
(8) from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
(9) to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
(10) ParOldGen total 10240K, used 7001K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
(11) object space 10240K, 68% used [0x00000000fec00000,0x00000000ff2d6630,0x00000000ff600000)
(12) PSPermGen total 21504K, used 4949K [0x00000000f9a00000, 0x00000000faf00000, 0x00000000fec00000)
(13) object space 21504K, 23% used [0x00000000f9a00000,0x00000000f9ed55e0,0x00000000faf00000)
分析
第一行是个警告,因为我测试的时候加了HandlePromotionFailure参数,这个参数在JDK1.7找不到,看提示说的removed掉了
2018-05-05T22:30:08.582+0800 这个数字就是执行GC的时间,这个很容易理解,使用参数"-XX:+PrintGCTimeStamps或者-XX:+PrintGCDateStamps"。
GC开石头的 “[GC"和”[Full GC"说明了这次垃圾收集的停顿类型,而不是用来区分新生代GC还是老年代GC的,如果有"Full"则说明GC发生了"Stop The World",如果在程序中调用了System.gc()方法,那显示的GC字样应该是"[Full GC(System)“这个样子的。
再往后面的”[PSYoungGen"表示GC发生的区域,这里显示的名字与当前JDK使用的收集器的名字相关(YoungGen就是表示新生代),常见的有如下几个
使用Serial收集器在新生代的名字是Default New Generation,因此显示的是"[DefNew"
使用ParNew收集器在新生代的名字会变成"[ParNew",意思是"Parallel New Generation"
使用Parallel Scavenge收集器在新生代的名字是"[PSYoungGen",这里的JDK1.7使用的就是PSYoungGen
老年代的收集和新生代道理一样,名字也是收集器决定的
说到收集器呢,就需要知道一下收集器使用的收集算法,常见是算法如下:
- 标记清除算法
- 复制算法
- 标记整理法
- 分代收集算法
不同的收集器呢对应不同的收集算法(不同版本可能有区别)
- Serial收集对应复制算法
- ParNew收集器对应复制算法
- Parallel Scavenge收集器对应复制算法
- Serial Old收集器对应复制算法
- Parallel Old收集器对应标记整理算法
- CMS收集器对应标记清除算法
- G1收集器对应标记整理
接着上面的分析,在后面的"[8184K->1000K(9216K)“含义是"GC前该内存区域的已使用容量->GC后该内存区域已使用容量(该内存区域总容量)”,在后面的"8184K->3398K(19456K), 0.0080798 secs" 含义是"GC前JAVA堆已使用容量->GC后Java堆已使用容量(java堆总容量),本次GC所占用的时间,单位是毫秒",再然后"[Times: user=0.02 sys=0.00, real=0.01 secs]"也是表示的时间,这个可以看看就行了。
上面的第二行和第三行是一样的意思
第四行"2018-05-05T22:34:16.813+0800: [Full GC [PSYoungGen: 952K->0K(9216K)] [ParOldGen: 8550K->7001K(10240K)] 9502K->7001K(19456K) [PSPermGen: 4940K->4939K(21504K)], 0.0267644 secs] [Times: user=0.02 sys=0.00, real=0.03 secs]“含义是"发生的时间,[GC的类型是Full GC [使用Parallel Scavenge收集器的新生代的内存区域大小的变化和总大小][使用ParNew收集器在老年代的内存区域变化和区域总大小],然后是[使用Parallel Scavenge在永久代的内存区域GC前后大小的变化和总大小],最后还是一个时间。”
再然后的就解释下名词好了,因为只是为了能看懂,真真用GC日志分析的话还远着我现在也不清楚
Heap(堆)
PSYoungGen(Parallel Scavenge收集器新生代) total 9216K, used 6234K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space(堆中的Eden区默认占比是8) 8192K, 76% used [0x00000000ff600000,0x00000000ffc16b08,0x00000000ffe00000)
from space(堆中的Survivor,这里是From Survivor区默认占比是1) 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
to space(堆中的Survivor,这里是to Survivor区默认占比是1,这个需要先了解一下堆的分配策略) 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
ParOldGen(老年代总大小和使用大小) total 10240K, used 7001K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space(显示个使用百分比) 10240K, 68% used [0x00000000fec00000,0x00000000ff2d6630,0x00000000ff600000)
PSPermGen(永久代总大小和使用大小) total 21504K, used 4949K [0x00000000f9a00000, 0x00000000faf00000, 0x00000000fec00000)
object space(显示个使用百分比,自己能算出来) 21504K, 23% used [0x00000000f9a00000,0x00000000f9ed55e0,0x00000000faf00000)
JVM内存区域详解(Eden Space、Survivor Space、Old Gen、Code Cache和Perm Gen)