前言

本节我们来通过代码实战来看下GC日志的一些信息。

代码示例

我们看以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.test;


public class TestGCLog01 {
private static final int _1MB = 1024*1024;
/**
* VM参数:
* -Xms20M -Xmx20M -Xmn10M -XX:+UseParallelGC -XX:+PrintGCDetails -XX:SurvivorRatio=8
*/
public static void testAllocation() {
byte[] allocation1, allocation2, allocation3, allocation4;
allocation1 = new byte[2*_1MB];
allocation2 = new byte[2*_1MB];
allocation3 = new byte[2*_1MB];
allocation4 = new byte[4*_1MB]; //出现一次 Minor GC
}

public static void main(String[] args) {
testAllocation();
}
}

代码比较简单,我们创建了四个字节数组,三个1M的,一个4M的。

下面我们来设置下JVM参数,有助于我们对GC日志进行分析。

设置JVM参数

我们设置的JVM参数如下:

1
-Xms20M -Xmx20M -Xmn10M -XX:+UseParallelGC -XX:+PrintGCDetails -XX:SurvivorRatio=8

JVM参数含义如下:

-Xms20M -Xmx20M ——> 堆大小:20M(最大值及最小值都是20M)

-Xmn10M——>年轻代的大小:10M

-XX:+UseParallelGC——>使用Parallel Scavenge垃圾回收器

-XX:+PrintGCDetails——>打印GC日志

-XX:SurvivorRatio=8——>年轻代中eden/survivor 空间大小的比例是8:1

GC日志解读

我们运行代码,打印出对应的GC日志信息:

GC日志的解读如下:

通过GC日志我们得出堆空间的占比如下:

分析代码逻辑,我们先创建了三个2M的对象,2M+2M+2M=6M,在Eden区中有6M的大小了,剩余2M的空间,然后再来一个4M的对象,Eden不够了,引发一次YoungGC,GC完成之后,根据GC日志:

发现Eden的使用率是78%,8M*78%=6.24M,剩余1M多的空间,4M的对象仍然存不进去,然后尝试存入s0或者s1区,发现空间不够用,那么只能存入老年代中去。所以老年代中有了这个4M的对象。

总结

我们通过一段简单的代码案例,及一些基础的JVM参数设置来实战打印出GC日志,并对GC日志的一些参数进行分析,让我们对GC日志有了更直观的认知。