[英]Why my JVM has so many old char and string?
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 沒有存活但仍然占據堆 memory。 這是正常的還是我需要擔心? 我希望 JVM 可以清理一些無用的字符串以保存 memory,因為我很確定所有這些字符串都是不同的,不會再次使用,也不需要保留在 ZCD69B4957F06CD818D7BF3D61980E2 9 以備將來重用。
我主要想知道jmap -histo: live
和jmap -histo
之間的區別, jmap -histo 中有超過 1000M 的 Char 但jmap -histo
jmap -histo:live
中只有 140M ,其他 860M 的字符在哪里? 為什么他們不是GC? 這些字符什么時候會是 GC? 如何讓它們立即 GC 以保存 memory?
正如@boneill 所指出的,在jmap -histo:live
的底層執行了一個完整的 GC... 以確定哪些對象是活動的。 而jmap -histo
... 沒有。
為什么我的 JVM 有這么多舊字符和字符串?
這是正常的還是我需要擔心?
這很難說。 證據不足。
但是,如果沒有其他證據,我會說“不關心”。
其他 860M 字符在哪里?
首先[C
並不意味着Char
。 這意味着char[]
。
他們在哪里? 好吧,我的閱讀是它們無法到達。 (不直播)。 它們是垃圾收集的候選者。
......為什么他們不是GC?
因為 GC 還沒有收集到它們。
Java 垃圾回收是……復雜的。 許多收集器是分代的,這意味着他們將堆分成新的和舊的 object 空間。 新空間被頻繁收集。 舊空間很少被收集。 因此,如果這些對象中的大多數已經被使用在舊空間中,它們可能會在它們變得無法訪問之后的相對較長的時間內存在。
這是一種可能的解釋。
這些字符什么時候會是 GC?
當舊空間被收集。 大概。
如何讓它們立即 GC 以保存 memory?
您可以調用System.gc()
來要求 JVM 運行(通常)完整的垃圾回收。 但...
為什么不保存 memory? 因為 JVM 掛在它返回的可用空間上......准備分配新對象。 因此 memory 不會返回給操作系統以供其他應用程序使用。 (堆大小調整有一些復雜的邏輯,但通常 JVM不情願地歸還 memory ;即僅在多個完整的 GC 周期之后。)
最后,在您的應用程序代碼中調用System.gc()
對性能不利……在大多數情況下。 還有其他問答可以解釋原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.