首页 > 解决方案 > 通过设置较低的新一代大小来控制进程的常驻内存是个坏主意吗?

问题描述

我们公司的支持团队报告我们的 API 进程消耗了太多 RAM,所以我开始分析这个问题,我使用了visualvmjconsole来监视进程,当我调用一个对 C++ 本机代码有JNI调用的端点时,我在顶级linux 监控软件的进程中看到常驻内存 (RES) 增长到超过最大堆大小(-Xmx JVM 标志)。例如 -Xmx3G 但 top 在多次命中端点后显示 6G。

最初我们认为这可能是本机内存泄漏,但我已经运行了一个测试,我每五秒使用System.gc()手动调用 GC,并且 RES 内存正常运行。

考虑到这个结果,我开始研究 JVM 标志和垃圾收集。我已经用串行收集器进行了测试,RES 内存做得很好,但由于它是一个 API,我更喜欢使用G1GC 收集器。在不明确执行的情况下更频繁地调用垃圾收集似乎是一个有趣的修复。但是,我找到的解决方案是将新生成大小设置为低值,我注意到 RES 内存中的显着峰值与分析 JConsole 的伊甸园空间中的峰值直接相关。

所以我将标志设置为-Xmn256M以尝试控制似乎没有在正常堆空间内分配的这个 RES 内存峰值,并尝试强制垃圾收集更频繁地运行,至少是从年轻到老的收集将军 然而,我注意到 G1GC 正在制作许多年轻的收藏,而没有旧的收藏。

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

正如你所见,年轻的集合被调用了 47 次,但老的集合从未被调用过。

所以,总而言之:我已经通过使用 G1GC 频繁运行年轻收集来控制常驻内存中的内存峰值,因为我注意到垃圾收集修复了这个内存过剩(RES >> Max Heap Size),即使不能解释一下,尽管我知道这种频繁的年轻收集可能会稍微影响应用程序的性能,因为 G1GC 的年轻代是通过停止所有应用程序线程来收集的(来自 Scott Oaks 的 Java Performance)。这是一个坏主意吗?我是否应该花更多时间来诊断内存泄漏(Java 或本机 C++)?

我完成这项任务的时间快到了

标签: javaperformancememory-leaksjvmjava-native-interface

解决方案


推荐阅读