怎么使用 jstack 分析一次线上内存溢出问题

  • 来源:网络
  • 更新日期:2022-01-17

摘要:怎么使用 jstack 分析一次线上内存溢出问题,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文

怎么使用 jstack 分析一次线上内存溢出问题,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

最近公司有一项业务在做活动,流量一下子大增。数据暴涨了 10 倍以上,系统无法支撑,导致了程序内存溢出,系统宕机。查看日志发现是有内存溢出的异常,今天就为大家分享一下如何使用 jstack 命令排查定位 java 程序中的异常代码。

为了讲清楚 jstack 的使用和我们系统产生的问题,我把线上问题简化为如下代码:


当你运行上面的代码时,你可能会期望它运行起来永远不会出问题,毕竟内置的缓存方案只会增加到10,000个元素,然后就不会再增加了,所有的 key 都已经出现在 HashMap 中(搞不懂 HashMap?只因你缺一个 HashMap 的流程图!、HashMap 存在的意义是什么?)。然而,事情并非如此。元素将会一直增长, 因为 Key 这个类只实现了 hashCode() 方法,并没有重写 equals() 方法(深度解读 Java 中的 equals()、==、hashCode())。

运行这个程序后,我们发现不需要太长的实际,程序就报内存溢出了。打开任务管理,此例中,找出 java 进程ID。


会了方便,大家也可以使用使用 ProcessExplorer 找到 ID 号为 7064 的 java 进程。进程 ID 为 7064 的属性信息在 Thread 标签找到 CPU 利用率的线程信息,TID 为 6120(10进制)。


将 CPU 利用率高的线程 ID 6120(10进制)转换为0x17E8(16进制)


使用 jstack 查看进程 7064 的线程信息。找到线程号为 0x17E8 的线程。命令:


根据提示的行号,我们定位到相关的代码。通过分析发现,是 map 造成的内存溢出。

解决方法很简单,只要和下面的示例一样添加一个 equals 方法就可以了。但是在找到问题所在之前,你肯定已经花费了不少宝贵的脑细胞。


jstack 命令很实用,是 java 虚拟机自带的一种堆栈跟踪工具。

看完上述内容,你们掌握怎么使用 jstack 分析一次线上内存溢出问题的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!


"新网虚拟主机"