jvm內存回收詭異現象,求解?

如圖所示,由於eden只有2M,所以3M進入old。但是eden使用率是62%,怎麼來的,求大神們幫解惑~謝謝


詭異嗎?不詭異~

要知道,一個java進程的啟動,到JVM的創建,然後找到你的Java文件主類中的main方法,經歷了一個「漫長」而有序的初始化過程。在此過程中,JDK中的WellKnown的N個class文件會被JVM預載入,在載入過程中,必然會創建包含className在內的各種各樣的SymbolName,這些字元串其實就是各種各樣的char[]數組,它們當然會佔據一定的堆空間;與此同時,與class文件相關的Java Mirror-Class對象也會一併創建——目測題主使用JDK1.8的版本,那麼這些java鏡像也會佔據一定的堆內存空間;當然初始化過程中還會有其他各種各樣的對象會預先佔據您所分配的eden區空間……然後執行到您的主類的時候,這個主類也要被載入,Class對象也要被創建,如果一切順利,在此過程中沒有因為您的年輕代分配的空間過小而發生Minor GC的話,就會經歷您要分配的3M的byte[]數組了,OK,發現年輕代沒有地方放,則直接晉陞到了Old區了~

所以,不要以為只有您寫得java程序會佔用Heap空間。


我想問問題主怎麼看虛擬機內存啊


ETIN 說的準確。這裡我根據你的代碼修改了下,列印了下heap。

讓當前線程掛起,方便列印堆內存。

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(1000000L);
}
}

使用命令:jmap -histo:live pid列印堆內存,結果如下(一部分):

從這裡可以看出,堆內存不僅僅是只有你創建的那個位元組數組,還有Java運行時自己初始化的一些對象。比如byte數組對象就有121個。

為了起到對比效果,我把代碼修改如下:

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(1000000L);
}
}

採用jmap列印結果:

可見,即使你不創建位元組數組,系統運行時也會有120個位元組數組。

其實也可以做如下實驗來證明:比如注釋掉申請位元組數組的語句,修改如下:

然後運行查看控制台:

依然會有68%的佔用。


推薦閱讀:

JVM的JIT優化所帶來的性能提升與C++之類比較那個好?
想做軟體開發,學哪種語言比較好?
聽說過面向工資編程嗎?面向工資編程是怎樣一種體驗?
需要前後端通吃嗎?

TAG:Java | Java虛擬機JVM | Java編程 | HotSpotVM |