如何在java中分析内存碎片?

2022-09-04 23:08:29

我们在服务器中遇到了几分钟的滞后。它们可能是由“停止世界”垃圾回收触发的。但是我们使用并发标记和扫描GC(-XX:+UseConcMarkSweepG),所以,我认为,这些暂停是由老一代的内存碎片触发的。

如何分析老一辈的记忆碎片化?有什么工具吗?

滞后每小时发生一次。大多数时候,它们大约是20秒,但有时 - 几分钟。


答案 1

查看 Java 文档,了解用于启用 GC 日志记录的“java -X...”选项。这将告诉您是收集旧一代还是新一代,以及收集需要多长时间。

“几分钟”的停顿听起来非同寻常。是否确定不只是在堆大小太小的情况下运行,或者在物理内存不足的计算机上运行?

  • 如果堆太接近满,GC 将被一次又一次地触发,从而导致服务器在 GC 中花费大部分 CPU 时间。这将显示在 GC 日志中。

  • 如果您在物理内存不足的计算机上使用大型堆,则完整的GC可能会导致计算机“崩溃”,从而花费大部分时间疯狂地将虚拟内存页移入和移出光盘。您可以使用系统监控工具对此进行观察;例如,通过在典型的UNIX / Linux系统上观看“vmstat 5”的控制台输出。

随访

与OP的信念相反,打开GC日志记录不太可能对性能产生明显影响。

了解 Oracle 站点上的“了解并发标记扫描垃圾回收器日志”页应该有助于解释 GC 日志。

最后,OP关于这是一个“碎片化”问题的结论不太可能,并且(IMO)没有得到他提供的证据片段的支持。它很可能是别的东西。


答案 2

对于低级监视,您将需要使用它(或者以更多的阻塞成本使其为2)。它是无证的,偶尔会给你一些统计数据。不幸的是,由于不同的原因,它在大多数应用程序中都不是很有用,但它至少是有用的。-XX:PrintFLSStatistics=1

例如,您应该能够看到

Max Chunk Size: 215599441

并将其与此进行比较

Total Free Space: 219955840

然后根据平均块大小和块数判断碎片。