我怎样才能找出对不确定对象持有什么?

问题描述:

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

One of our programs is sometimes getting an OutOfMemory error on one user's machine, but of course not when I'm testing it. I just ran it with JProfiler (on a 10 day evaluation license because I've never used it before), and filtering on our code prefix, the biggest chunk both in total size and number of instances is 8000+ instances of a particular simple class.

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

I clicked the "Garbage Collect" button on JProfiler, and most instances of other classes of ours went away, but not these particular ones. I ran the test again, still in the same instance, and it created 4000+ more instances of the class, but when I clicked "Garbage Collect", those went away leaving the 8000+ original ones.

这些实例在各个阶段都会陷入各种集合中。我假设他们没有被垃圾收集的事实必须意味着某件东西持有对其中一个集合的引用,这样就保留了对这些对象的引用。

These instances do get stuck into various Collections at various stages. I assume that the fact that they're not garbage collected must mean that something is holding onto a reference to one of the collections so that's holding onto a reference to the objects.

任何建议如何我可以找出什么是持有的参考?我在寻找的代码,以及如何寻找什么建议,找出这在JProfiler的,如果有。

Any suggestions how I can figure out what is holding onto the reference? I'm looking for suggestions of what to look for in the code, as well as ways to find this out in JProfiler if there are.

转储堆并检查它。

我确信有多种方法可以做到这一点,但这是一个简单的方法。这个描述适用于MS Windows,但在其他操作系统上可以采取类似的步骤。

I'm sure there's more than one way to do this, but here is a simple one. This description is for MS Windows, but similar steps can be taken on other operating systems.


  1. 如果您还没有安装JDK它。 它附带了一堆整洁的工具

  2. 启动应用程序。

  3. 打开任务管理器并查找java.exe的进程标识(PID)(或者您正在使用的任何可执行文件)。如果PID没有默认显示,请使用View> Select Columns ...添加它们。

  4. 使用 jmap 转储堆。

  5. 在您生成的文件上启动 jhat 服务器,并打开浏览器 http:// localhost:7000 (默认端口是7000)。现在,您可以浏览您感兴趣的类型以及实例数量,引用它们的信息等等。

  1. Install the JDK if you don't already have it. It comes with a bunch of neat tools.
  2. Start the application.
  3. Open task manager and find the process id (PID) for java.exe (or whatever executable you are using). If the PID's aren't shown by default, use View > Select Columns... to add them.
  4. Dump the heap using jmap.
  5. Start the jhat server on the file you generated and open your browser to http://localhost:7000 (the default port is 7000). Now you can browse the type you're interested in and information like the number of instances, what has references to them, etcetera.

这是一个例子:

Here is an example:

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.

为了解释这一点,了解一些阵列型命名法 Java使用 - 等知道的类[ Ljava.lang.Object; 确实意味着 Object [] 类型的对象。

To interpret this, it is useful to understand some of the array type nomenclature Java uses - like knowing that class [Ljava.lang.Object; really means an object of type Object[].