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

相關文章
相關標籤/搜索