背景
千呼万唤始出来,终于找到时间去整理一下有关堆内存溢出的记录啦,其实是最近工作真的太忙啦,问题太多啦,好吧,是我太懒,太菜。偶尔在网上发一下疯哈。
Java heap space
经常出Bug的朋友会知道,java.lang.OutOfMemoryError: Java heap space,Java应用程序创建的对象存放在这片区域,垃圾回收(Garbage Collection)也发生在这块区域。通常一些比较“重型”的操作可能会导致该异常,比如:需要创建大量的对象,层次比较深的递归操作等。
解决方案
1.优化应用
找到消耗大量内存的地方,然后优化代码或者算法。这种方式比较推荐,但是难度比较大,尤其是在产品环境中出现这种问题,开发人员不能很好的重现问题,这个时候就需要用到堆内存分析工具了。
2.提升Java heap size
这种方式虽然感觉有点治标不治本,但是可行性非常高,操作简单。 “JVM 堆空间溢出(java.lang.OutOfMemoryError: Java heap space)”错误是JVM 堆空间不足,此时只需要调整-Xms 和-Xmx 这两个参数即可,根据自己的需要调整。
参考如下:
服务器内存8G ,所以可以采取以下配置: JAVA_OPTS=-server -Xms4096m -Xmx4096m -XX:PermSize=256M -XX:MaxNewSize=512m -XX:MaxPermSize=512m 服务器内存4G ,所以可以采取以下配置: JAVA_OPTS=-server -Xms2048m -Xmx2048m -XX:PermSize=256M -XX:MaxNewSize=512m -XX:MaxPermSize=512m 服务器内存2G ,所以可以采取以下配置: JAVA_OPTS=-server -Xms1024m -Xmx1024m -XX:PermSize=256M -XX:MaxNewSize=512m -XX:MaxPermSize=512m 服务器内存1G ,所以可以采取以下配置: JAVA_OPTS=-server -Xms512m -Xmx512m -XX:PermSize=128M -XX:MaxPermSize=256M -XX:MaxPermSize=256m 服务器内存512M ,所以可以采取以下配置: JAVA_OPTS=-server -Xms256m -Xmx256m -XX:PermSize=256M -XX:MaxNewSize=128m -XX:MaxPermSize=128m Tomcat内存优化主要是对 tomcat 启动参数优化,我们可以在 tomcat 的启动脚本 catalina.sh 中设置 JAVA_OPTS 参数。 JAVA_OPTS参数说明 -server 启用jdk 的 server 版; -Xms java虚拟机初始化时的最小内存; -Xmx java虚拟机可使用的最大内存; -XX:PermSize 内存永久保留区域 -XX:MaxPermSize 内存最大永久保留区域
下面就来详细介绍一下dump文件的分析过程
分析步骤
1.生成堆内存的dump文件
2.dump文件下载
3.使用JVisualVM等Java监控工具来生成堆内存的报告
JVisualVM下载和使用
使用JVisualVM等Java监控工具来生成堆内存的报告
三个实例持有的对象太多导致堆区内存被占满,导致的内存溢出的错误(占用运行内存70%)
生成后发现堆文件大小有5到6G,windows环境下,拉到本地来分析或者使用图形化软件来分析(MAT、visualvm 堆查看器使用的内存不足),下载传输的时间较长,有时候会无法加载,无法查看具体造成堆内存溢出的对象,于是在网上搜罗了一番,准备通过linux上的mat工具进行分析,将dump文件传输到linux服务器上进行分析(需要剩余内存大于5G)
Memory Analyzer下载和使用
根据jdk版本下载合适的mat版本,可以通过uname -a命令查看服务器的操作系统版本号,我们使用的是jdk1.8,x86_64,所以下载的是图示的版本。
准备工作就绪执行分析命令,分析完成会生成很多文件在dump文件所在的目录下,最好新增一个文件夹存储,以防文件太多错乱。
nohup ./ParseHeapDump.sh ./dumpfile.hprof org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components & echo $! > pid
分析完成后会生成三个包:
org.eclipse.mat.api:suspects #表示生成内存泄露报告
org.eclipse.mat.api:overview #表示生成概述报告
org.eclipse.mat.api:top_components #表示生成大对象报告
排查内存泄露问题可以主要看java_pid_Leak_Suspects.zip这个压缩包下的内容。点击detail,划到页面最下方可以看到thread stack,定位到具体代码位置,再实际排查代码问题。
有出错的地方希望大家提出,我会积极改善和更新。非常感谢以下参考文档的作者,真的是帮了我一个大忙。