在知乎上看到一篇提問,因而作了個實驗幫助他解答,這裏整理成一篇文章分享一下。數組
先看代碼以下代碼:對象
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數組對象等等。
------------------------------------------------------------------------------
這裏是跟阿里的技術大牛建立的一個圈子,主要面向初學者提供輔導幫助。有興趣的能夠加入。