[英]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.