我的应用程序加载了大约的数据集。每次 85bm 至 100mb。应用程序的内存限制设置为 512mb,理论上来说,这已经足够了。
然而,我发现,如果在应用程序的单次运行中,我打开和关闭数据集 5 次,总内存消耗会稳步增加,直到出现内存不足错误:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6882 bguiz 20 0 679m 206m 19m S 30 13.7 0:30.22 java
6882 bguiz 20 0 679m 259m 19m S 9 17.2 0:55.53 java
6882 bguiz 20 0 679m 301m 19m S 9 20.0 1:20.04 java
6882 bguiz 20 0 679m 357m 19m S 33 23.7 1:44.74 java
6882 bguiz 20 0 679m 395m 19m S 80 26.2 2:10.31 java
内存从约 14% 增长到约 26%。看起来像是内存泄漏。
发生的情况是,正在加载的顶级数据用于填充地图和列表等集合,然后使用更详细的数据创建这些顶级对象的子对象,然后它们依次创建子对象- 子对象。
当数据集关闭时,当前应用程序确实尝试通过取消填充各种对象集合来清除其轨迹,然后显式调用System.gc();
无论如何,这就是我收到应用程序时的状态(在我之前已经制作了几年),并且我被分配了这项任务。
我需要做的是找到一种方法来找到数据集卸载后哪些子对象和子子对象仍在相互引用,并纠正它们。
显然,这可以手动完成,但会非常非常繁琐,但我觉得通过内存分析来完成此操作会是一个更好的选择,这是我以前没有做过的事情。
我读过一些其他 SO 问题,询问要使用哪种内存分析工具,我选择使用 Netbeans IDE 中内置的工具,因为它似乎有很好的评论,而且无论如何我都在 Netbeans 中工作。
有没有人之前执行过类似的 Java 内存分析任务,事后看来:
- 您会给我什么具体建议?
- 您发现哪些技术对解决这个问题有用?
- 您发现哪些资源对解决这个问题有用?
编辑:
该应用程序是标准桌面应用程序 - 不是 Web 应用程序。
编辑:已实施的解决方案
基本上对我有用的是将 Netbeans 的分析器与 JHAT 结合使用。
我发现 Netbeans IDE 中内置的 Profiler 在创建内存转储方面做得非常好分析点,然后该工具能够按类进行过滤和排序,并深入了解每个实例的引用。这一切都非常好。
但是,它没有为我提供比较两个堆转储的方法。我问了一个跟进问题,看起来 JHAT(作为 JDK 的一部分)很好地完成了这项工作。
Thorbjørn Ravn Andersen、Dmitry 和 Jason Gritman:你们的意见非常有帮助,不幸的是我只能将 1 标记为正确答案,无论如何你们都从我这里得到了 +1。