簡體   English   中英

為什么我的 JVM 有這么多舊字符和字符串?

[英]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: livejmap -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 運行(通常)完整的垃圾回收。 但...

  1. JVM 可能會完全忽略該請求,
  2. 它可能不會運行完整的 GC(這可能取決於實現),
  3. 即使收集了對象,您也很可能不會保存任何實際的 memory

為什么不保存 memory? 因為 JVM 掛在它返回的可用空間上......准備分配新對象。 因此 memory 不會返回給操作系統以供其他應用程序使用。 (堆大小調整有一些復雜的邏輯,但通常 JVM不情願地歸還 memory ;即僅在多個完整的 GC 周期之后。)

最后,在您的應用程序代碼中調用System.gc()對性能不利……在大多數情況下。 還有其他問答可以解釋原因。

暫無
暫無

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

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