JVM——简单分析GC

634 阅读2分钟

前言

GC常用相关参数和堆内存使用情况 - 掘金 (juejin.cn)

这篇文章讲了GC的常用参数与查看堆内存情况

首先我们创建DemoTest类添加main方法,并添加jvm参数:-Xms20M -Xmx20M -Xmn10M -XX:+UserSerialGC -xx:+PrintGCDetails -verbose:gc

然后运行空的main方法,内容如下(具体意义看上篇文章)

image.png

分析GC

在main方法中创建一个ArrayList里面放入数组byte[],并使该对象为栈帧上的局部变量引用堆里面的对象,那么这个对象在运行期间由于GC Root引用所以它不会被回收。

然后往对象里面加入5Mbyte数组,通过上面图看到Eden中已经被占用了百分之45,然后再放入5M显然Eden是存不下的这里肯定就会触发以下垃圾回收,代码如下

    private static final int SEVEN_MB = 7 * 1024 * 1024;
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(new Byte[SEVEN_MB]);
    }

运行后结果:

1637590815(1).jpg

如果是老年代发生的GC最前面会提示Full GC新生代发生的GC就叫做GC

DefNew 后面的两个值前面代表回收前的大小后面表示回收后的大小,括号中表示新生代的总大小,在后面跟着的数值就是代表新生代垃圾回收执行的时间。

执行时间之后的信息是整个堆执行前占用情况和执行后占用情况,括号中表示堆的总大小,再之后就是整个堆的回收时间

然后内存区域也发生了改变,Eden被占用了百分之就是,由于GC的时候幸存区From和幸存区To内存会发生交换,所以幸存区内存空间被占用了百分之六十五

image.png

继续往数组中添加byte数组,这里再添加 1M:

    private static final int SEVEN_MB = 7 * 1024 * 1024;
    private static final int _1MB = 1 * 1024 * 1024;
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(new Byte[SEVEN_MB]);
        list.add(new Byte[_1MB]);
    }

再次运行查看GC信息:

image.png

这里触发了两次垃圾回收,老年代中已经被占用了百分之七十六的空间。

继续添加byte数组,这里再添加 15M

private static final int SEVEN_MB = 7 * 1024 * 1024;
private static final int _15MB = 15 * 1024 * 1024;
private static final int _1MB = 1 * 1024 * 1024;
public static void main(String[] args) {
    ArrayList list = new ArrayList();
    list.add(new Byte[SEVEN_MB]);
    list.add(new Byte[_1MB]);
    list.add(new Byte[_15MB]);
}

image.png

再添加15M已经超出了我们设置的堆内存最大大小,所以抛出了堆内存溢出的错误信息,并且还进行了一次 Fubll GC