JVM 配置参数及GC收集器的日志解析
接下来将深入了解学习 JVM,以简单有效的方式整理相关知识,如有本人有错误见解之处,敬请留言告知!谢谢~~
** 注:**IDEA 如何配置打印 GC 日志,大家可以 Google、百度一下。
# 一。参数分类
根据 JVM 参数开头可以区分参数类型,共三类:“-”、“-X”、“-XX”,
标准参数(-):所有的 JVM 实现都必须实现这些参数的功能,而且向后兼容;
例子:-verbose:class,-verbose:gc,-verbose:jni……
非标准参数(-X):默认 jvm 实现这些参数的功能,但是并不保证所有 jvm 实现都满足,且不保证向后兼容;
例子:Xms20m,-Xmx20m,-Xmn20m,-Xss128k……
非 Stable 参数(-XX):此类参数各个 jvm 实现会有所不同,将来可能会随时取消,需要慎重使用;
例子:-XX:+PrintGCDetails,-XX:-UseParallelGC,-XX:+PrintGCTimeStamps……
# 二。参数详解
-XX:+
-XX:-
-XX:
1 | -Xms # Java堆的初始大小 |
# 三. GC 日志解析
# 1. 正常日志
Java8 默认的 GC 收集器
1 | 参数示例: |
PSYoungGen total 7168K, used 2197K
-
PSYoungGen:新生代采用了 Parallel Scavenge 收集器 (PS: Parallel Scavenge)
-
total 7168K:共有 7168K
-
used 2197K:已使用 2197K
eden space 6144K, 35% used
(默认 Eden : from : to = 8 : 1 : 1,可以通过 –XX:SurvivorRatio 调整)
- 伊甸区,共有 6144K,已使用 %35
from space 1024K, 0% used
- 幸存区 S0,共有 1024K,已使用 %0
to space 1024K, 0% used
- 幸存区 S1,共有 1024K,已使用 %0
ParOldGen total 12288K, used 0K
-
ParOldGen:表示老年代采用 Parallel Old 收集器 (Par: Parallel Old)
-
total 12288K:共有 12288K
-
used 0K:已使用 0K
object space 12288K, 0% used
- 老年代,共有 12288K,已使用 %0
Metaspace used 3099K, capacity 4496K, committed 4864K, reserved 1056768K
-
Metaspace:元空间
-
jdk1.7 之前,HotSpot 虚拟机对于⽅法区的实现称之为 “永久代 (Permanent Generation)”
-
jdk1.8 之后,HotSpot 虚拟机对于⽅法区的实现称之为 “元空间 (Meta Space)”
# 2. 垃圾回收日志
Java8 默认的 GC 收集器
- 代码示例
1 | /** |
- GC 日志
1 | 2020-11-06T21:05:43.932+0800: 0.131: [GC (Allocation Failure) [PSYoungGen: 2229K->936K(7168K)] 10421K->9136K(19456K), 0.0008828 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] |
2020-11-06T21:05:43.932+0800: 0.131: [GC (Allocation Failure) [PSYoungGen: 2229K->936K(7168K)] 10421K->9136K(19456K), 0.0008828 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
-
2020-11-06T21:05:43.932+0800:GC 日志记录时间
-
0.131:GC 发生的时间,Java 虚拟机启动以来运行的秒数
-
GC (Allocation Failure):发生了一次垃圾回收。如果有 “Full”,说明这次 Full GC 是发生了 Stop-The-World (STW)。没有,则就次就是 Minor GC。** 注意不是用来区分新生代 GC 还是老年代 GC。**Allocation Failure 的原因是新生代中没有足够的内存能够存放需要分配的数据而失败。
-
PSYoungGen:使用的 GC 收集器名称 (PS: Parallel Scavenge)。
-
2229K->936K (7168K):GC 前该内存区域已使用容量 ->GC 后该内存区域已使用容量 (该内存区域总容量)
-
10421K->9136K (19456K):GC 前 Java 堆已使用容量 ->GC 后 Java 堆已使用容量 (Java 堆总容量)
-
0.0008828 secs:该内存区域 GC 所占用的时间,单位是秒
-
[Times: user=0.00 sys=0.00, real=0.00 secs]:分别表示用户态消耗的 CPU 时间、内核态消耗的 CPU 时间和总耗时
2020-11-06T21:05:43.936+0800: 0.134: [Full GC (Ergonomics) [PSYoungGen: 5277K->4844K(7168K)] [ParOldGen: 8200K->8192K(12288K)] 13477K->13036K(19456K), [Metaspace: 3276K->3276K(1056768K)], 0.0046614 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
- 2020-11-06T21:05:43.936+0800:GC 日志记录时间
- 0.134:GC 发生的时间,Java 虚拟机启动以来运行的秒数
- Full GC (Ergonomics):发生了一次 Full GC (Ergonomics),且是一次全局 GC
- [PSYoungGen: 5277K->4844K (7168K)]:新生代进行了一次 GC。[GC 收集器名称:GC 前该内存区域已使用容量 ->GC 后该内存区域已使用容量 (该内存区域总容量)]
- [ParOldGen: 8200K->8192K (12288K)] :老年代进行了一次 GC。[GC 收集器名称:GC 前该内存区域已使用容量 ->GC 后该内存区域已使用容量 (该内存区域总容量)]
- 13477K->13036K (19456K):GC 前 Java 堆已使用容量 ->GC 后 Java 堆已使用容量 (Java 堆总容量)
- [Metaspace: 3276K->3276K (1056768K)]:元空间 (方法区) 进行了一次 GC。但是 GC 前后内存使用情况并没有发生任何变化,且元空间总容量为 1G
- 0.0046614 secs:该内存区域 GC 所占用的时间,单位是秒
- [Times: user=0.00 sys=0.00, real=0.00 secs]:分别表示用户态消耗的 CPU 时间、内核态消耗的 CPU 时间和总耗时
# 3.Serial 收集器日志
- 代码示例
1 | /** |
- GC 日志
1 | [GC (Allocation Failure) [DefNew: 6178K->744K(7424K), 0.0028888 secs] 6178K->4840K(19712K), 0.0029277 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] |
[GC (Allocation Failure) [DefNew: 6178K->744K(7424K), 0.0028888 secs] 6178K->4840K(19712K), 0.0029277 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
-
GC (Allocation Failure):发生了一次垃圾回收
-
DefNew:Serial 收集器中的新生代名称为 “Default New Generation”
-
6178K->744K (7424K):GC 前该内存区域已使用容量 ->GC 后该内存区域已使用容量 (该内存区域总容量)
-
0.0028888 secs:该内存区域 GC 所占用的时间,单位是秒
-
6178K->4840K (19712K):GC 前 Java 堆已使用容量 ->GC 后 Java 堆已使用容量 (Java 堆总容量)
-
[Times: user=0.00 sys=0.02, real=0.00 secs] :分别表示用户态消耗的 CPU 时间、内核态消耗的 CPU 时间和总耗时
[Full GC (Allocation Failure) [Tenured: 8932K->8903K(12288K), 0.0015452 secs] 13029K->13000K(19712K), [Metaspace: 3152K->3152K(1056768K)], 0.0015649 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
- Full GC (Allocation Failure):发生了一次 Full GC
- [Tenured: 8932K->8903K (12288K), 0.0015452 secs]:老年代进行了一次 GC。[GC 收集器名称:GC 前该内存区域已使用容量 ->GC 后该内存区域已使用容量 (该内存区域总容量),GC 耗时]
- 13029K->13000K (19712K):GC 前 Java 堆已使用容量 ->GC 后 Java 堆已使用容量 (Java 堆总容量)
- [Metaspace: 3152K->3152K (1056768K)]:元空间 (方法区) 进行了一次 GC。但是 GC 前后内存使用情况并没有发生任何变化,且元空间总容量为 1G
- [Times: user=0.00 sys=0.00, real=0.00 secs]:分别表示用户态消耗的 CPU 时间、内核态消耗的 CPU 时间和总耗时
# 4.ParNew 收集器日志
- 代码示例 (ParNew + Serial Old)
1 | /** |
- GC 日志
1 | [GC (Allocation Failure) [ParNew: 6178K->768K(7424K), 0.0026432 secs] 6178K->4882K(19712K), 0.0026981 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] |
[GC (Allocation Failure) [ParNew: 6178K->768K(7424K), 0.0026432 secs] 6178K->4882K(19712K), 0.0026981 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
-
GC (Allocation Failure):发生了一次垃圾回收
-
ParNew:ParNew 收集器中的新生代名称为 “Parallel New Generation”
-
6178K->768K (7424K):GC 前该内存区域已使用容量 ->GC 后该内存区域已使用容量 (该内存区域总容量)
-
0.0026432 secs:该内存区域 GC 所占用的时间,单位是秒
-
6178K->4882K (19712K):GC 前 Java 堆已使用容量 ->GC 后 Java 堆已使用容量 (Java 堆总容量)
-
[Times: user=0.00 sys=0.00, real=0.00 secs] :分别表示用户态消耗的 CPU 时间、内核态消耗的 CPU 时间和总耗时
※ 其他的就不解释了,如上示例分析即可
# 5.Parallel Scavenge 收集器
- 代码示例 (Parallel Scavenge + Parallel Old)
1 | /** |
- GC 日志
1 | [GC (Allocation Failure) [PSYoungGen: 2228K->936K(7168K)] 10420K->9136K(19456K), 0.0015886 secs] [Times: user=0.05 sys=0.03, real=0.00 secs] |
※ 其他的就不解释了,如上示例分析即可
**[Full GC (Ergonomics) [PSYoungGen: 5277K->4846K(7168K)] [ParOldGen: 8200K->8192K(12288K)] 13477K->13038K(19456K), [Metaspace: 3300K->3300K(1056768K)], 0.0049473 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] **
- Full GC (Ergonomics) :发生了一次 Full GC (Ergonomics)
- [PSYoungGen: 5277K->4846K (7168K)]:新生代: GC 前该内存区域已使用容量 ->GC 后该内存区域已使用容量 (该内存区域总容量)
- [ParOldGen: 8200K->8192K (12288K)]:老年代:GC 前该内存区域已使用容量 ->GC 后该内存区域已使用容量 (该内存区域总容量)
- 13477K->13038K (19456K):GC 前 Java 堆已使用容量 ->GC 后 Java 堆已使用容量 (Java 堆总容量)
- [Metaspace: 3300K->3300K (1056768K)]:元空间: GC 前后内存使用情况并没有发生任何变化,且元空间总容量为 1G
- 0.0049473 secs:该内存区域 GC 所占用的时间,单位是秒
- [Times: user=0.00 sys=0.00, real=0.01 secs]:分别表示用户态消耗的 CPU 时间、内核态消耗的 CPU 时间和总耗时
# 6.CMS 收集器日志
-
GC 日志 (ParNew + CMS)
新生代:采用 stop-the-world mark-copy 算法;
年老代:采用 Mostly Concurrent mark-sweep 算法;
1 | 参数示例: |
[GC (Allocation Failure) [ParNew: 613404K->68068K(613440K), 0.1020465 secs] 10885349K->10880154K(12514816K), 0.1021309 secs] [Times: user=0.78 sys=0.01, real=0.11 secs]
-
GC (Allocation Failure):发生了一次垃圾回收
-
ParNew:ParNew 收集器中的新生代名称为 “Parallel New Generation”
-
613404K->68068K (613440K):GC 前该内存区域已使用容量 ->GC 后该内存区域已使用容量 (该内存区域总容量)
-
0.1020465 secs:该内存区域 GC 所占用的时间,单位是秒
-
10885349K->10880154K (12514816K):GC 前 Java 堆已使用容量 ->GC 后 Java 堆已使用容量 (Java 堆总容量)
-
[Times: user=0.78 sys=0.01, real=0.11 secs]:分别表示用户态消耗的 CPU 时间、内核态消耗的 CPU 时间和总耗时
[GC (CMS Initial Mark) [1 CMS-initial-mark: 10812086K(11901376K)] 10887844K(12514816K), 0.0001997 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
- GC (CMS Initial Mark):发生了一次 STW 垃圾回收 (CMS 初始标记)
- CMS-initial-mark:1> CMS 初始化标记
- 10812086K (11901376K):当前老年代已使用容量 (老年代总容量)
- 10887844K (12514816K):当前 Java 堆已使用过容量 (Java 堆总容量)
- [Times: user=0.00 sys=0.00, real=0.00 secs]:分别表示用户态消耗的 CPU 时间、内核态消耗的 CPU 时间和总耗时
[CMS-concurrent-mark-start]
- [CMS-concurrent-mark-start]:CMS 启动并发标记
[CMS-concurrent-mark: 0.035/0.035 secs]
- CMS-concurrent-mark:2> CMS 并发标记
- 0.035/0.035 secs:该阶段持续的时间和时钟时间
[CMS-concurrent-preclean-start]
- [CMS-concurrent-preclean-start]:CMS 启动并发预清理
[CMS-concurrent-preclean: 0.016/0.016 secs]
- CMS-concurrent-preclean:**3> **CMS 并发预清理
- 0.016/0.016 secs:该阶段持续的时间和时钟时间
[CMS-concurrent-abortable-preclean-start]
- [CMS-concurrent-abortable-preclean-start]:CMS 启动并发可终止预清理
[CMS-concurrent-abortable-preclean: 0.167/1.074 secs]
- CMS-concurrent-abortable-preclean:4> CMS 并发可终止预清理
- 0.167/1.074 secs:该阶段持续的时间和时钟时间
[GC (CMS Final Remark) [YG occupancy: 387920 K (613440 K)]65.550: [Rescan (parallel) , 0.0085125 secs]65.559: [weak refs processing, 0.0000243 secs]65.559: [class unloading, 0.0013120 secs]65.560: [scrub symbol table, 0.0008345 secs]65.561: [scrub string table, 0.0001759 secs][1 CMS-remark: 10812086K(11901376K)] 11200006K(12514816K), 0.0110730 secs]
- GC (CMS Final Remark) :发生了一次 STW 垃圾回收 (**5>**CMS 最终标记)
- [YG occupancy: 387920 K (613440 K)]:新生代当前已使用容量 (总容量)
- [Rescan (parallel) , 0.0085125 secs]:这个阶段在应用停止的阶段完成存活对象的标记工作
- [weak refs processing, 0.0000243 secs]:第一个子阶段,进行弱引用处理
- [class unloading, 0.0013120 secs]:第二个子阶段,卸载未使用的类
- [scrub symbol table, 0.0008345 secs]:最后一个子阶段,清理分别保存类级元数据和内部化字符串的符号表和字符串表
- 10812086K (11901376K):在这个阶段之后老年代占有的内存大小和老年代的容量
- 11200006K (12514816K):在这个阶段之后整个堆的内存大小和整个堆的容量
[CMS-concurrent-sweep-start]
- [CMS-concurrent-sweep-start]:CMS 启动并发清除
[CMS-concurrent-sweep: 0.027/0.027 secs]
- CMS-concurrent-sweep:6> CMS 并发清除
- 0.027/0.027 secs:该阶段持续的时间和时钟时间
[CMS-concurrent-reset-start]
- [CMS-concurrent-reset-start]:CMS 启动并发重置
[CMS-concurrent-reset: 0.012/0.012 secs]
- CMS-concurrent-reset:7> CMS 并发重置
- 0.012/0.012 secs:该阶段持续的时间和时钟时间
# 7.G1 收集器
- 代码示例 G1
1 | /** |
- GC 日志
1 | 2020-11-08T00:20:23.316+0800: [GC pause (G1 Humongous Allocation) (young) (initial-mark), 0.0011210 secs] |