我为制作团队编写了一个应用程序来衡量他们的分数,它可以正常运行 2-3 周,然后运行副本的机器速度变慢,重新启动即可修复。
解决此问题的最佳实践步骤是什么?
最佳答案
您需要分析堆并找出哪些对象被保留在那里,而这些对象不应该被保留。
一个选项:
尝试减少 -Xmx
最大堆大小以加速内存不足异常,在启动时将此选项添加到 jvm -XX:+HeapDumpOnOutOfMemoryError
然后加载生成类似 Eclipse Memory Analyzer 的堆转储.
另一种选择:
使用 jmap 从正在运行的进程中转储堆(可能需要 sudo 权限)
jmap -heap:format=b <pid>
再次,将堆转储二进制文件加载到 jhat 或 Eclipse 内存分析器中。
如果您的应用正在变慢但没有抛出 OutOfMemoryError,则很可能您没有泄漏,但您确实需要做一些事情 JVM tuning因为它在 GC 上花费了太多时间。
您应该监控 GC 收集时间(您可以使用 -Xloggc:/tmp/gc.out
记录它们)或者您可以使用 jstat
查看 GC 的频率发生以及需要多长时间。
如果您的应用程序有很多中等生命周期的对象,那么新生代是否足够大 (-XX:NewRatio=N
)?否则,您的应用程序将花费很长时间将对象提升到老年代,但之后不久就必须对它们进行 GC(老年代的 GC 相对于新年代而言是昂贵的,尤其是当您的内存碎片化时)。
此外 - 您是否启用了 CMS 收集器?如果你有一台多核机器,我建议你这样做(-XX:+UseConcMarkSweepGC
)。
关于java - 如何着手查找 Java 应用程序中的内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7613429/