首页 > 解决方案 > 我应该使用内存分析器中的哪种模式(采样/检测)来确保我摆脱了 Java 中的内存泄漏?

问题描述

我的 Java 应用程序遇到了内存泄漏,我正在尝试解决这个问题。但是,根据我在分析运行期间选择的模式,我会得到相反的结果。因此,我不确定我所针对的内存泄漏是否已经解决,因为最近在生产中出现了“内存不足错误:Java 堆空间”。

Visual Studio Code有一个指南来了解这两种模式之间的区别(采样/检测或跟踪探查器,还有这个关于 VisualVM 同一主题的忍者指南。我知道使用检测模式的开销要高得多。但是需要这种模式(至少在 Netbeans 分析器中)来获取具有最多“幸存世代”数量的对象列表,这是要观察的指标,以便查看对抗内存的对策的效率泄漏。

感谢 OOM 堆栈跟踪,我知道哪种方法导致了内存泄漏,因此我能够在单元测试中将其隔离。

我的单元测试一开始是@RunWith(JfxTestRunner.class)为了避免在将某些内容发送到 Java Fx 应用程序线程时(即在 GUI 应用程序中向用户显示某些内容时)出现有关“工具包未初始化错误”的错误。

现在,如果我启动此单元测试(循环读取 Solr 索引的内容并根据此内容填充列表)并在采样模式下对其进行分析,我会得到以下图表:

采样轮廓中的记忆形状 采样配置文件中内存中的对象

这让我认为问题已经解决,因为使用的堆在索引读取期间增加,之后减少。

但是现在,如果我在所有类的仪器模式下运行相同的测试(参见下面的“*”),我会得到一个非常不同的内存形状:

仪表化配置文件中的记忆形状 检测配置文件中内存中的对象

这次使用的堆随着时间的推移不断增加,就好像仍然存在内存泄漏一样。

我首先使用检测模式来获取保持垃圾回收的对象,然后在没有注意的情况下切换到采样模式并认为问题已经解决。现在我很不确定。

因此,我想知道我的评估应该基于哪种模式(采样/仪器),以及为什么会出现这种差异(仪器模式下的内存占用更高,而在这种模式下存活的世代大约要高出一倍)。

任何帮助表示赞赏,

亲切的问候

标签: javamemory-leaksvisualvmmemory-profiling

解决方案


推荐阅读