簡體   English   中英

Java不需要的內存分配

[英]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. 將程序從休眠狀態更改為1毫秒而不是5000。(實際數量無關緊要……這是為了使假設的內存分配盡可能快地進行。您也可以嘗試0毫秒,但是睡眠行為可能會有所不同...)

  2. 使用當前方法運行程序; 例如與jconsole。

  3. 在不使用jconsole等的情況下運行該程序,但使用“ -verbose:gc”選項,以便您可以看到GC何時運行。

我懷疑您在等待GC在最后一種情況下運行時會失去耐心,甚至會盡可能快地進入sleep

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM