jmap -histo {pid} 顯示以下結果:
num #instances #bytes class name
----------------------------------------------
1: 4787259 1007093680 [C
2: 6049019 191502048 [B
3: 198580 125701976 [I
4: 5212228 125093472 java.lang.String
雖然運行jmap -histo:live {pid}顯示以下結果:
num #instances #bytes class name
----------------------------------------------
1: 463375 140980752 [C
2: 9832 63080312 [I
3: 563438 31161448 [B
4: 461206 11068944 java.lang.String
你可以看到有很多 Char 和 String 沒有存活但仍然占用堆記憶體。這是正常現象還是我需要擔心?我希望 JVM 可以清理一些無用的字串以節省記憶體,因為我很確定所有這些字串都是不同的,不會再次使用,也不需要保留在記憶體中以備將來重用。
我主要是想知道之間的區別jmap -histo: live和jmap -histo,有超過字符在1000Mjmap -histo但只有在140M jmap -histo:live,哪里是其他860M字符?為什么他們不是GC?這些字符什么時候會成為 GC?我怎樣才能讓它們立即 GC 以節省記憶體?
uj5u.com熱心網友回復:
正如@boneill 指出的那樣,在幕后jmap -histo:live執行完整的 GC ......以確定哪些物件是活動的。而且jmap -histo……沒有。
為什么我的 JVM 有這么多舊的字符和字串?
這是正常現象還是我需要擔心?
這很難說。證據不足。
但是,在沒有其他證據的情況下,我會說“不關心”。
其他 860M 字符在哪里?
首先[C不代表Char。這意味著char[]。
他們在哪里?好吧,我的閱讀是它們無法訪問。(不直播)。它們是垃圾收集的候選者。
......為什么他們不是GC?
因為 GC 還沒有收集它們。
Java 垃圾收集是……復雜的。許多收集器是分代的,這意味著它們將堆分成新的和舊的物件空間。新空間經常收集。舊空間很少收集。因此,如果這些物件中的大多數都在舊空間中使用,那么它們在變得無法訪問后可能會存活相對較長的時間。
這是一種可能的解釋。
這些字符什么時候會成為 GC?
當舊空間被收集。大概。
我怎樣才能讓它們立即 GC 以節省記憶體?
您可以呼叫System.gc()要求 JVM 運行(通常)完整的垃圾收集。但 ...
- JVM 可能會完全忽略該請求,
- 它可能不會運行完整的GC(這可能取決于實作),
- 即使收集了物件,您也很可能不會保存任何實際記憶體。
你為什么不節省記憶體?因為 JVM 掛在它回傳的可用空間上......準備分配新物件。因此記憶體不會回傳給作業系統供其他應用程式使用。(調整堆大小有一些復雜的邏輯,但通常 JVM不情愿地返還記憶體;即只有在多次完整的 GC 周期之后。)
最后,System.gc()在大多數情況下,呼叫應用程式代碼對性能不利。還有其他問答可以解釋原因。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/369859.html
