JVM——简单分析GC

这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战

前言

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是存不下的这里肯定就会触发以下垃圾回收,代码如下

1
2
3
4
5
js复制代码    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:

1
2
3
4
5
6
7
js复制代码    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

1
2
3
4
5
6
7
8
9
arduino复制代码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

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%