Java 内存分析:如何检测哪个应用程序/包占用了太多内存
我在工作中遇到过这样一种情况:我们运行一个JavaEE服务器,上面部署了几个应用程序。最近,我们经常发生OutOfMemoryException。我们怀疑一些应用程序可能表现不好,可能是泄漏或其他什么 问题是,我们真的不知道是哪一个。我们已经运行了一些内存分析器(比如YourKit),它们非常擅长判断哪些类使用的内存最多。但是它们没有显示类之间的关系,所以这就给我们留下了这样一种情况:我们看到,比如说,有很多字符串、int数组和HashMap条目,但我们无法真正区分它们来自哪个应用程序或包Java 内存分析:如何检测哪个应用程序/包占用了太多内存,java,jakarta-ee,memory-leaks,profiling,memory-management,Java,Jakarta Ee,Memory Leaks,Profiling,Memory Management,我在工作中遇到过这样一种情况:我们运行一个JavaEE服务器,上面部署了几个应用程序。最近,我们经常发生OutOfMemoryException。我们怀疑一些应用程序可能表现不好,可能是泄漏或其他什么 问题是,我们真的不知道是哪一个。我们已经运行了一些内存分析器(比如YourKit),它们非常擅长判断哪些类使用的内存最多。但是它们没有显示类之间的关系,所以这就给我们留下了这样一种情况:我们看到,比如说,有很多字符串、int数组和HashMap条目,但我们无法真正区分它们来自哪个应用程序或包 有没
有没有一种方法可以知道这些对象来自何处,这样我们就可以确定分配了最多内存的包(或应用程序)?一个简单的想法是,如果您不介意一些性能折衷的话,您可能可以做些反思……在这种情况下可以做几件事:
- 。从1.5天开始,通过JVM参数可以使用此功能。获得转储后,可以使用以下工具对其进行脱机分析:。重要的部分是找出支配树
- 在测试服务器上执行内存分析;他擅长这个。在分析根本原因时,这肯定比第一次需要更多的时间,因为必须存在内存分配失败的确切情况。如果您有自动集成/功能测试,那么推断根本原因将更容易。诀窍是定期进行堆转储,并分析导致堆消耗增加的类。可能不一定存在泄漏-可能是堆大小不足的情况
- 我发现有帮助的是:
jmap -J-d64 -histo $PID
(删除32位arch的-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
然后,您可以尝试进一步诊断问题,进行差异分析,以及不比较连续快照的内容
这只会使虚拟机暂停一小段时间,即使是在大堆的情况下,这样您就可以在生产中安全地执行此操作(在非高峰时间,希望是:)您是否已将探查器连接到各个应用程序?或者只是到应用服务器?你有办法在测试服务器上拆分它们吗。。给每个人一个较小的最大堆。。。观察哪一个会爆炸?您还可以启用GC日志并查看堆的新旧区域的大小。使用“-verbose:gc-XX:+PrintGCDetails XX:+PrintGCTimeStamps–Xloggc:PATH_FROM_ROOT/gclog.log”为starters@JeffStorey:我们已经将探查器(YourKit和JRockit任务控制)连接到JVM本身。如何将探查器附加到应用服务器中的特定应用?这当然会有所帮助@bwawok:是的,我们也考虑过这个选项,尽管它需要一些设置和校准:我们不知道我们的应用程序需要多少内存(即使表现良好)@josek:我们现在正在启用gc日志,尽管我们没有分析它们的经验。@malvim。当它们都在运行时,将它们连接到应用服务器可能会很困难。您可以在应用服务器上一次运行一个,然后连接到应用服务器吗?或者如果您在本地计算机上(您不能远程执行堆转储),只运行
jvisualvm