java - 我怎样才能弄清楚未释放的对象持有什么?

标签 java garbage-collection jprofiler

我们的一个程序有时会在一个用户的机器上出现 OutOfMemory 错误,但在我测试它时当然不会。我只是用 JProfiler 运行它(在 10 天的评估许可证上,因为我以前从未使用过它),并过滤我们的代码前缀,总大小和实例数量的最大块是一个特定简单类的 8000 多个实例.

我点击了 JProfiler 上的“垃圾收集”按钮,我们其他类的大多数实例都消失了,但这些特定的没有。我再次运行测试,仍然在同一个实例中,它创建了 4000 多个类的实例,但是当我单击“垃圾收集”时,那些实例消失了,留下了 8000 多个原始实例。

这些实例确实会在不同阶段陷入不同的集合中。我假设它们没有被垃圾收集这一事实一定意味着某些东西持有对其中一个集合的引用,因此它持有对对象的引用。

有什么建议可以让我弄清楚引用中的内容吗?我正在寻找关于在代码中寻找什么的建议,以及在 JProfiler 中找到它的方法(如果有的话)。

最佳答案

转储堆并检查它。

我敢肯定有不止一种方法可以做到这一点,但这里有一个简单的方法。此描述适用于 MS Windows,但可以在其他操作系统上执行类似步骤。

  1. 如果您还没有 JDK,请安装它。 It comes with a bunch of neat tools.
  2. 启动应用程序。
  3. 打开任务管理器并找到 java.exe(或您正在使用的任何可执行文件)的进程 ID (PID)。如果默认情况下未显示 PID,请使用“查看”>“选择列...”来添加它们。
  4. 使用 jmap 转储堆。
  5. 在您生成的文件上启动jhat 服务器并打开浏览器到 http://localhost:7000 (默认端口为 7000)。现在您可以浏览您感兴趣的类型和信息,例如实例数量、对它们的引用等。

这是一个例子:

C:\dump>jmap -dump:format=b,file=heap.bin 3552

C:\dump>jhat heap.bin
Reading from heap.bin...
Dump file created Tue Sep 30 19:46:23 BST 2008
Snapshot read, resolving...
Resolving 35484 objects...
Chasing references, expect 7 dots.......
Eliminating duplicate references.......
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

要解释这一点,了解一些 array type nomenclature 是很有用的Java 使用 - 就像知道 class [Ljava.lang.Object; 实际上意味着 Object[] 类型的对象。

关于java - 我怎样才能弄清楚未释放的对象持有什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/154309/

相关文章:

java - Java 存储 native 对象的位置

java - 在 jboss eap 6.3 中加载属性文件

memory-management - 使用 valgrind 调试自定义内存分配器时, "pool"的作用是什么?

c# - 循环引用对象的垃圾回收

c++ - gcroot 的这种用法安全吗?

java - JPA - 为什么我在数据库中的每一行看到两个实体实例?

java - 从另一个调用 java 程序

java - 如何序列化/反序列化 (JSON) ArrayLIst<A>,它在 Java 中有一个 ArrayLIst<B> 作为字段

java - 如何使用PDF OCR批量处理文件?

java - 性能测试与分析