[英]Java unrequested memory allocation
在JConsole下觀察到的以下代碼顯示了堆大小的不斷增加。 堆最大達到25mb,然后GC運行並將堆大小減小到將近3MB。 這是預期的行為嗎? 我很驚訝!
public class Dummy {
public static void main(String[] args) {
System.out.println("start");
while(true){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
我正在使用雪豹。
與jconsole進行通信會導致分配對象。 我相信您在這里看到的是您的測量方法的產物。 編譯代碼時,HotSpot可能還會分配一些資源。 如果您擔心,請使用探查器查看正在分配的內容(再次,注意探查器的界面是否分配)。
正常的GC行為是為了避免不必要的運行。 您將在整個Web上看到內存使用情況的鋸齒圖。 在緩存和交換友好性之間存在一些折衷,並且避免了工作。 另外,服務器HotSpot在使用內存方面比客戶端HotSpot更積極。
是的,這應該是預期的行為。 盡管您沒有做任何特定於分配對象的事情,但是睡眠的實現可能是,即使沒有實現,JVM中也可能運行着其他線程。
是的,很正常。 您沒有顯式創建任何對象,但是您正在調用可能創建一些臨時對象作為其實現的一部分的方法。 這些臨時對象會堆積起來,直到需要運行GC清除它們為止。
類文件看起來像這樣,代碼從8循環到14,並且java.lang.Thread.sleep()是本機的。 因此,沒有理由創建對象的MB
public static void main(java.lang.String[] args);
0 getstatic java.lang.System.out : java.io.PrintStream [16]
3 ldc <String "start"> [22]
5 invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]
8 ldc2_w <Long 5000> [30]
11 invokestatic java.lang.Thread.sleep(long) : void [32]
14 goto 8
17 astore_1 [e]
18 aload_1 [e]
19 invokevirtual java.lang.InterruptedException.printStackTrace() : void [38]
22 goto 8
恐怕您看到的是來自JProfiler本身(我不知道您是如何將其附加到Dummy測試應用程序的)或在此vm中運行的其他內容。 要找出已創建的對象,如果JProfiler不顯示此信息,則應進行堆轉儲。
'
關於起因,顯然有兩種理論,並且不可能基於經驗推理來區分它們。 我可以建議一個簡單的實驗。
將程序從休眠狀態更改為1毫秒而不是5000。(實際數量無關緊要……這是為了使假設的內存分配盡可能快地進行。您也可以嘗試0毫秒,但是睡眠行為可能會有所不同...)
使用當前方法運行程序; 例如與jconsole。
在不使用jconsole等的情況下運行該程序,但使用“ -verbose:gc”選項,以便您可以看到GC何時運行。
我懷疑您在等待GC在最后一種情況下運行時會失去耐心,甚至會盡可能快地進入sleep
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.