java垃圾回收诡异现象

java

在知乎上看到一篇提问,于是做了个实验帮助他解答,这里整理成一篇文章分享一下。

先看代码如下代码:

 1 /**

2 * Created on 2017/12/16.

3 *

4 * -verbose:gc -XX:+UseSerialGC -Xms6M -Xmx6M -Xmn2M -XX:+PrintGCDetails

5 */

6 public class TestHeap {

7 private static final int _1MB = 1024*1024;

8

9 public static void main(String[] args) throws Exception{

10 byte[] b = new byte[3*_1MB];

11 }

12 }

运行时加上注释里的JVM参数,控制台打印如下

问题是:分配一个3m的数组,新生代只有2m,所以对象直接分配到年老代。通过打印结果也可以看出来,年老代用了3072k,正好是我们的3m数组。但是为什么新生代居然还有68%不占用呢?

简单猜想一下,肯定是Java在运行时自己创建了一些对象占用了新生代空间。好我们来验证下。

将代码为什么也不做:

/**

* Created on 2017/12/16.

*

* -verbose:gc -XX:+UseSerialGC -Xms6M -Xmx6M -Xmn2M -XX:+PrintGCDetails

*/

public class TestHeap {

private static final int _1MB = 1024*1024;

public static void main(String[] args) throws Exception{

//byte[] b = new byte[3*_1MB];

}

}

控制台打印如下:

即使执行创建字节数组语句,新生代依旧被占用68%。可以说我们假象成立。

不信?

那好吧,咱们就打印下此时Java堆空间里的对象来看看。

 咱们是用jmap命令来打印出堆里的对象看看,顺便复习下jmap的使用。

我们使用如下命令:

jmap -histo:live pid 

注意:此命令不能在线上执行,因为会触发JVM的fullgc。

代码不变,依旧是注释掉字节数组的创建语句。只不过为了方便执行jmap命令,咱们让它暂停下,以防进程退出。 

/**

* Created on 2017/12/16.

*

* -verbose:gc -XX:+UseSerialGC -Xms6M -Xmx6M -Xmn2M -XX:+PrintGCDetails

*/

public class TestHeap {

private static final int _1MB = 1024*1024;

public static void main(String[] args)throws Exception{

//byte[] b = new byte[3*_1MB];

Thread.sleep(100000L);

}

}

执行jmap命令结果如下(部分截图):

看到了,我们啥都不做都有1544个char数组对象,120个byte数组对象等等。

---------------------------------------------------------------------------------------------------------------------

这里是跟阿里的技术大牛创建的一个圈子,主要面向初学者提供辅导帮助。有兴趣的可以加入。

https://t.xiaomiquan.com/aEQVNJe

以上是 java垃圾回收诡异现象 的全部内容, 来源链接: utcz.com/z/392551.html

回到顶部