简单例子读懂JVM报告

1.首先,了解下什么是JVM报告?

2. 然后,看看如何设置控制台打印JVM报告?

复制-verbose:gc -XX:+PrintGCDetails到run configuration的VM options

3.接着,那这个报告里面到底有什么有价值的信息呢?

- 用了哪个垃圾回收器

- 新生代大小

    - eden区大小和使用情况

    - to survivor区大小和使用情况

    - from survivor区大小和使用情况

- 老年代大小和使用情况

- minorGC和Full GC是否发生和发生具体情况

 上面两张图没写的信息基本可以忽略

4. 最后,我们通过一个真实案例来解释上面的数据会不会更好理解呢?

首先创建JVMTest

代码如下,创建4个数组和进行一次full gc

public class JVMTest {

    private static final int M = 1024 * 1024;

    public static void main(String[] args) {
        byte[] b1 = new byte[2 * M];
        byte[] b2 = new byte[2 * M];
        byte[] b3 = new byte[2 * M];
        byte[] b4 = new byte[4 * M];
        System.gc();
    }
}

然后我们来设置一下JVM参数(为什么我要设置?因为刚开始学,写死这些参数,更方便我们观察)

-verbose:gc -XX:+PrintGCDetails -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8

解释下参数的意思:

// 打印堆信息
-verbose:gc -XX:+PrintGCDetails
// 指定堆内存的大小20M
-Xms20M -Xmx20M
// 指定新生代内存10M
-Xmn10M
// 指定Eden Survivor1,Survivor2之间内存比例为(8:1:1)
-XX:SurvivorRatio=8

现在新生代和老生代都是10M,而新生代里Eden8M,两个Surviror都是1M

接着执行我们的代码

看到了下图

JVM报告的意思是

发生了两次GC,一次Minor GC,目前已使用内存为4M(4782k);发生了一次Full GC,目前已使用内存10M;

eden区一共8M,已使用61%即使用了4~5M

survivor区0%,原因是被gc了

the space老年区一共10M,使用了6M

接着我们从代码的角度解释为什么内存会这样分配

public static void main(String[] args) {
        byte[] b1 = new byte[2 * M];
        byte[] b2 = new byte[2 * M];
        byte[] b3 = new byte[2 * M];
        byte[] b4 = new byte[4 * M];
        System.gc();
    }

首先创建了3次2m大小的数组,此时eden区一共8M大小,被使用了6M,接着b4创建一个4M大小的数组,eden区发现不够空间,执行一次minor GC,且根据“内存分配策略”,动态对象年龄判断:幸存区相同年龄对象的占幸存区空间的多于其一半,将进入老年代 ,所以此时这三个2M数组被划进老年区,老年区一共10M,此时变成6M,eden区清空,此时b4顺利存入eden区。

完~

猜你喜欢

转载自blog.csdn.net/qq_38056704/article/details/87818172
今日推荐