java - Java 桌面应用程序的内存分析

标签 java memory-management memory-leaks garbage-collection profiling

我的应用程序加载了大约一个数据集。每次 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%。看起来像是内存泄漏。

发生的事情是,正在加载的顶级数据用于填充 map 和列表等集合,然后更详细的数据用于创建这些顶级对象的子对象,然后它们在转而创建子子对象。

当数据集关闭时,当前应用程序确实尝试通过取消填充各种对象集合来清除其踪迹,然后显式调用 System.gc();


无论如何,这就是我到达应用程序时的状态(在我之前已经准备好几年了),我被分配了这个任务。

我需要做的,就是想办法找出数据集卸载后哪些子对象和子子对象还在互相引用,并纠正它们。
显然,这可以手动完成,但会非常乏味,但我觉得通过内存分析来完成此操作是一个更好的选择,这是我以前从未做过的事情。

我已经阅读了一些其他 SO 问题,这些问题询问要使用哪些内存分析工具,我选择使用 Netbeans IDE 中内置的工具,因为它似乎有很好的评价,而且无论如何我都在 Netbeans 中工作。

有没有人以前做过类似的 Java 内存分析任务,事后看来:

  • 你会给我什么具体的建议?
  • 您发现哪些技术对解决这个问题有用?
  • 您发现哪些资源对解决这个问题有用?

编辑: 此应用程序是标准桌面应用程序 - 不是 Web 应用程序。


编辑:已实现的解决方案

基本上对我有用的是将 Netbeans 的分析器与 JHAT 结合使用。

我发现 Netbeans IDE 中内置的 Profiler 在特定分析点 创建内存转储方面做得非常好,然后该工具能够按类进行过滤和排序,并向下钻取每个实例的引用。这一切都非常好。

但是,它没有为我提供比较两个堆转储的方法。我问了一个follow up question ,看起来 JHAT(作为 JDK 的一部分)很好地完成了这项工作。

Thorbjørn Ravn Andersen、Dmitry 和 Jason Gritman:你们的意见非常有帮助,不幸的是我只能将 1 标记为正确答案,无论如何你们都从我这里得到了 +1。

最佳答案

我在 https://stackoverflow.com/questions/1716597/java-memory-leak-detection-tools/1717260#1717260 上写了关于查找内存泄漏技术的另一个问题的答案。

如果你听从我的建议,像 JProfiler 这样的工具可以让您遍历对象的引用图并查看这些对象的深度大小。这可以帮助您找到仍然持有数据的任何对象。

我没有使用过 Netbeans,所以我无法告诉您它与我使用过的其他分析器相比如何。如果它看起来不像具有该功能,您可以轻松获得 JProfiler 的试用版,它应该会持续到您发现泄漏。

关于java - Java 桌面应用程序的内存分析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1752714/

相关文章:

c++ - 如何销毁包含自引用指针的对象?

c# - 追踪 .NET Windows 服务内存泄漏

linux - apache、tomcat 和 mod_jk 和 mysql 的内存泄漏

c++ - 由于 new() 或 malloc 导致内存泄漏

java - 我需要单击名为“使用 java 中的 selenium webdriver 注册新闻通讯”的复选框

java - 为什么使用 GenericServlet 无法进行 session 管理?

java - 我想实现 DRY 原则,但不知道如何实现

android - 管理 fragment 事务时优化 Android 中的内存

C 或 C++ 堆内存管理实现

java - 使用外部 jar 文件从命令行运行 java 应用程序