内存分析:如何检测哪个应用程序/包占用了太多内存

时间:2010-06-01 23:02:54

标签: java java-ee memory-leaks profiling memory-management

我在这里遇到一种情况,我们运行的Java EE服务器上部署了多个应用程序。最近,我们经常遇到OutOfMemoryException。我们怀疑某些应用程序可能表现不佳,可能是泄漏,或者其他什么。

问题是,我们无法确定哪一个。我们已经运行了一些内存分析器(比如YourKit),并且它们非常善于告诉哪些类使用最多的内存。但是它们没有显示类之间的关系,所以这给我们留下了这样的情况:我们看到有很多字符串和int数组以及HashMap条目,但是我们无法确定它们是哪个应用程序或包来自。

有没有办法知道这些对象来自哪里,所以我们可以尝试查明分配最多内存的软件包(或应用程序)?

3 个答案:

答案 0 :(得分:3)

在这种情况下,有几件事情可以做:

  • Configure the Java EE application server to produce a heap dump on OOME。自1.5天起,此功能可通过JVM参数获得。获得转储后,可以使用Eclipse MAT等工具离线分析。重要的是找出支配树。
  • 在测试服务器上执行内存分析; Netbeans擅长这一点。在分析根本原因时,这必然需要花费更多时间,因为必须存在内存分配失败的确切条件。如果您确实进行了自动集成/功能测试,那么推断根本原因会更容易。诀窍是定期进行堆转储,并分析导致堆消耗增加的类。可能不一定存在泄漏 - 可能是堆大小不足的情况。

答案 1 :(得分:0)

一个快速的想法是,如果你不介意一些表现权衡,你可能会做一些反思....

答案 2 :(得分:0)

我发现有用的是:

jmap -J-d64 -histo $PID

(删除32位拱的-J-d64选项)

这将输出如下内容:

num     #instances         #bytes  class name
----------------------------------------------
1:       4040792     6446686072  [B
2:       3420444     1614800480  [C
3:       3365261      701539904  [I
4:       7109024      227488768  java.lang.ThreadLocal$ThreadLocalMap$Entry
5:       6659946      159838704  java.util.concurrent.locks.ReentrantReadWriteLock$Sync$HoldCounter

然后从那里你可以尝试进一步诊断问题,做差异以及不比较连续快照的内容。

这只会暂停VM一段时间,即使对于大堆也是如此,因此您可以安全地在生产中执行此操作(在非高峰时段,希望:):