最近客户的生产环境经常出现问题,搞的头大,测试在开发环境、模拟环境又复现不了,没法进行实时跟踪,最后只能从hprof文件进行分析,这篇文章就是记录内存溢出问题分析过程的记录。
一、遇到这类问题,首先简单看下CPU、内存使用情况,大概了解下,然后把服务启动,在保证服务先运行的情况下,再把hprof从生产环境Copy本地,hprof文件如下所示,最好不要在生产环境来进行分析问题,这样有些危险。
- hprof 如何生成,只需要在jar启动的时候,加上如下参数设置即可:
- -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${目录}
- -XX:+HeapDumpOnOutOfMemoryError 参数表示当JVM发生OOM时,自动生成DUMP文件。
- -XX:HeapDumpPath=${目录}参数表示生成DUMP文件的路径,也可以指定文件名称,例如:-XX:HeapDumpPath=${目录}/java_heap.hprof。如果不指定文件名,则默认为:java<pid><date><time>heapDump.hprof。建议设置目录即可。
- 生成的文件大概如下
二、进行OOM分析,常用的工具有jvisualvm、ibm ha457.jar、JProfiler(收费)。
三、用jvisualvm打开hprof文件,如图所示,
1. 可以直接看到hprof的基本信息及OOM的线程,点击线程链接,查看错误信息。
- OOM详细错误如下显示,可以清楚的看出是Arrays.copyOf时出现内存溢出,再继续往下跟踪,可以看到跟zookeeper,后面更是看到具体是跟zookeeper的Client有关,我们再继续点击引起溢出的数组,看看里面存放的什么数据,更利于我们问题追踪。
- 点击引起溢出的byte数组,查询里面数据如图所示,这里应该就知道问题是出现在哪里了,比如,下面数据是我们的服务注册中心的服务链接信息,所以范围就圈定在有监听zookeeper节点更新的地方,基本就能锁定问题。
- 然后我们再弄ibm ha打开同样的hprof,可以看到如下效果,LinkedBlockingQuere积压了,哪就更明确了,直接在项目中哪些地方有添加服务且是用LinkedBlockingQuere队列存储的地方就基本能解决问题了。
四、经过我们再项目中确认及测试,最终确认是zookeeper的客户端在监听node变动时,消费过慢导致溢出溢出,也就是如下这里导致的。
问题找到,解决就相对容易些,既然是OOM,肯定是内容过多,可以采用数据压缩、数据精简、数据分离存储等等方案,我们最终是数据部分放在分布式的Redis,zookeeper的data自存入极少数数据,方案迭代后问题得以解决。
- 总结下找问题思路,遇到问题首先要拿到原始文件,然后分析,可能会有不同的辅助工具来分析日志、或者二进制文件,尽量用多个工具打开看下,因为每个工具关注的角度可能不一样,这对我们分析问题非常有帮助,更利于确认问题发的根源,然后就是找到问题点,解决问题,测试,迭代到生产
如果条友喜欢,还请给个关注
评论(0)