接下来将深入了解学习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] |
最后更新: 2021年04月01日 11:03