jvm内存回收诡异现象

在知乎上看到一篇提问,因而作了个实验帮助他解答,这里整理成一篇文章分享一下。数组

先看代码以下代码:对象

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%不占用呢?get

简单猜测一下,确定是Java在运行时本身建立了一些对象占用了新生代空间。好咱们来验证下。io

将代码为何也不作:class

/**
 * 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];
    }
}

控制台打印以下:map

即便执行建立字节数组语句,新生代依旧被占用68%。能够说咱们假象成立。gc

不信?im

那好吧,我们就打印下此时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

相关文章
相关标签/搜索