VM参数
1、在控制台打印出每次GC信息:
1 | -XX:+PrintGCDetails |
2、在发生OOM时打印出堆栈信息:
1 | -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/chuan/ |
OOM代码
发生OOM测试程序代码,也可以自行编写,运行VM参数(-Xms1m -Xmx1m -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/chuan/
)
1 | public class OOMDemo { |
Minor GC日志
[GC --[PSYoungGen: 447K->447K(1024K)] 709K->956K(1536K), 0.0031459 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
下面来解析这一段信息,其实很简单,不用硬记,按顺序从左到右:
-
GC:表示这是发生了GC
-
PSYoungGen:GC类型,此处表示新生代内存发生了GC;
-
447K->447K:->前面的447K表示GC前新生代内存占用,->后面的447K表示GC后新生代内存占用(此处是分毫未被回收,那你执行个骡子,浪费 0.0031459秒);
-
(1024K):1024K表示新生代总共大小,看得出来是1M,可以回头看一下VM参数配置;
-
709K->956K:709K表示GC前JVM堆内存使用,956表示GC后JVM堆内存使用(硌老子的,GC后还变多了);
-
(1536K):1536K表示JVM堆内存总大小;
-
0.0031459 secs:本次GC耗时(看得出还是很快的);
-
user:GC用户耗时;
-
sys:GC系统耗时;
-
real:GC实际耗时。
Full GC日志
[Full GC [PSYoungGen: 447K->197K(1024K)] [ParOldGen: 508K->494K(512K)] 956K->692K(1536K), [Metaspace: 3179K->3179K(1056768K)], 0.0069504 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
-
Full GC:GC类型;
-
[PSYoungGen: 447K->197K(1024K)] :Young区,447K表示GC前Young区内存占用,197K表示GC后Young区内存占用,1024K表示Young区总大小;
-
[ParOldGen: 508K->494K(512K)] :Old区,508K表示GC前Old区内存占用,494K表示GC后Old区内存占用,512K表示Old区总大小;
-
956K->692K(1536K):956K表示GC前JVM堆内存使用,692K表示GC后JVM堆内存使用,1536K表示JVM堆内存总大小;
-
[Metaspace: 3179K->3179K(1056768K)]:元空间,3179K表示GC前后元空间的使用,1056768K表示元空间的总大小(使用VM参数 -XX:-UseCompressedClassPointers -XX:MetaspaceSize=50M指定元空间的总大小);
-
0.0069504 secs:本次GC耗时(看得出还是很快的);
-
user:GC用户耗时;
-
sys:GC系统耗时;
-
real:GC实际耗时。
规律
[名称:GC前内存->GC后内存(总内存)]
1 | Heap |
解析上述:
PSYoungGen total = eden space + from space,内存地址eden+from+to
ParOldGen GC前后老年代的内存变化