今天刚刚才加一个故障review会议, 故障非常典型, google下也可以找到相似案例介绍。 在排查问题的过程中,使用了大量的工具, 发现有问题的地方还不只一个,总结一下. (本篇文章不会重点描述案例本身,重点会介绍个人对java内存泄露问题的排查思路和各种工具的使用)。
解决方案:
方案1(直接有效): 使用btrace相关工具输出调用ClassLoader.defineClass栈信息, 从栈信息来追溯问题. (代码如下图). 但Btrace 不能trace jvm native方法(官方release btrace 1.3.1中版本声明可以trace native方法, 但尝试无效。如果你清楚如何使用,麻烦告知一下,谢谢).  * **用JProfiler来trace String.intern方法栈 * 方案2: dump heap, 看看哪些class有异常现象(数量), String被Perm区引用的对象信息等.但这种方式不太直观,可以从String数据看看发现可疑问题,没有方案1直观。(如下图: 如果能在日常调试推荐JProfiler**)  * 方案3: 增加-XX:+TraceClassLoading和-XX:+TraceClassUnloading, 看看哪些class加载了,哪些class卸载了. 如果一些特殊的class一直被加载而没有被卸载说明也是有问题的。(如下图)  * 方案4:执行jmap -permgen(jstat -gcutil 可以查看内存增长速度和区域)命令看看Perm区中的内容, 初步确定是否存在问题 (如下图)解决方案:
触发FullGC, dump live heap. 标记堆中对象数量, 重点关注可疑对象触发FullGC, dump live heap. 标记堆中对象数量, 重点关注可疑对象对比步骤1和步骤2 相同对象的数量和大小, 找出可疑对象一一进行排查确认。如果步骤3依然无法明确有问题的对象, 那就多执行几次步骤1和步骤2。 在此过程中可以调整GC触发时间, 模拟真实的故障场景 :)看看GC后堆的大小是否增长, 如果没有不断增长, 并且持续一段较长时间, 那基本正常(具体看看深入浅出JProfiler文章中的实践章节)。注: Java内存泄露的场景还有很多(可以参考下官方的一些文档java memleaks), 有机会后面会继续补充.
相关资源:敏捷开发V1.0.pptx