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

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

这些实例确实在各个阶段陷入了各种Collection中。我假设它们不是垃圾收集的事实,这意味着某些内容正在保留对集合之一的引用,从而保留了对对象的引用。

关于如何找出引用的任何建议?我正在寻找有关在代码中查找内容的建议,以及在JProfiler中找到此内容的方法。

最佳答案

转储并检查堆。

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

  • 如果尚未安装JDK,请安装它。 It comes with a bunch of neat tools.
  • 启动应用程序。
  • 打开任务管理器,并找到java.exe(或正在使用的任何可执行文件)的进程ID(PID)。如果默认情况下未显示PID,请使用“ View ”>“选择列...”添加它们。
  • 使用jmap转储堆。
  • 在生成的文件上启动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.
    

    为了解释这一点,了解Java的array type nomenclature的使用很有用-例如知道类[Ljava.lang.Object; 实际上是指 Object [] 类型的对象。

    10-07 19:03
    查看更多