繁体   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