1.Jar
1.1.使用java命令配置jvm启动参数
1.1.1.Windows命令
java -jar -Xms5m -Xmx5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\dump test2.jar
1.1.2.Linux命令
java -jar -Xms5m -Xmx5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/dev/dump test2.jar
2.Tomcat
2.1.Windows环境
①.添加JVM参数
在Tomcat的bin目录,打开catalina.bat,添加如下参数(HeapDumpOnOutOfMemoryError 默认输出位置为Tomcat的bin目录下):
set “JAVA_OPTS=-Xms512M -Xmx1024M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapdump”
当产生OOM错误时,会将dump镜像文件生成到D:\heapdump\java_pid4288.hprof
②.校验是否生效
1)JDK8以下版本
执行命令jvisualvm,查看参数是否生效。
2)JDK9以上版本
从JDK9开始,将不在集成visualVM ,需要自行下载安装:https://visualvm.github.io/download.html
也可以使用jconsole查看。
2.2.Linux环境
①.添加JVM参数
在Tomcat的bin目录,打开catalina.sh,添加如下参数(HeapDumpOnOutOfMemoryError 默认输出位置为Tomcat的bin目录下):
JAVA_OPTS="-Xms200M -Xmx200M -XX:+HeapDumpOnOutOfMemoryError"
②.校验是否生效
在bin目录下的执行命令 ./startup.sh ,然后在命令窗口输入命令 jps -v(执行不了可以到jdk的bin目录下执行);也可以添加 -XX:HeapDumpPath=/home/dev/来指定输出的位置。
JAVA_OPTS="-Xms200M -Xmx200M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/dev/"
3.OOM分析
3.1.Jvisualvm分析dump文件
3.1.1.JDK8以下版本
可以利用工具Jvisualvm进行分析
依次点击 文件 -> 装入 选择对应的.hprof文件
通过实例数占比可以判断出产生OOM的主要原因。
点击indexing(线程名不一定相同)
这里可以看到产生OOM的线程。
3.1.2.JDK9以上版本
从JDK9开始,将不在集成visualVM ,需要自行下载安装:
地址:https://visualvm.github.io/download.html
3.2.Eclipse的MAT分析dump文件
3.2.1.MAT工具安装
下载地址: https://www.eclipse.org/mat/downloads.php 解压即可
在解压后的目录执行命令:
./ParseHeapDump.sh /home/dev/dump/java_pid23571.hprof org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components &echo $! > pid
如果文件很大,可以使用以下命令:
nohup c./ParseHeapDump.sh /home/dev/dump/java_pid23571.hprof org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components &echo $! > pid
注意这里使用了nohup ,因为对于大文件的分析,并不能保证shell窗口的活动时间,所以使用nohup,并保存了pid,以便于查看是否执行完毕。
执行完成之后,结果会生产如下三个zip文件,将文件传到本地
- java_pid23571_Leak_Suspects.zip
- java_pid23571_System_Overview.zip
- java_pid23571_Top_Comp.zip
3.2.2.查看报告的方法
3.2.2.1.直接把zip下载到本地,然后解压用浏览器查看index.html
从这里可以获取产生OOM异常的类:
3.2.2.2.用MAT可视化工具MemoryAnalyze分析dump的hprof文件
3.3.Idea中分析dump文件
3.3.1.测试案例
3.3.1.1.测试代码
3.3.1.2.配置参数
-Xms5m -Xmx5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/dev/dump
3.3.1.3.输出结果
3.3.2.Dump文件导入Idea
3.3.2.1.将生成的hprof文件拖入当前项目中
3.3.2.2.GC Root
双击count最大的那个类
然后再鼠标右键 Jump to source就可以直接到达对应的代码中。
3.4.IBM HeapAnalyzer 工具
HeapAnalyzer允许通过启发式搜索引擎查找可能的Java™堆泄漏区域,并分析Java应用程序中的Java堆转储。
Java堆区定义了对象,数组和类。当垃圾收集器分配堆中的存储区域时,对象继续处于活动状态,而其引用存在于JVM的活动状态中某处; 因此该对象是可到达的。当一个对象停止从活动状态被引用时,它变成垃圾并且可以被回收再利用。发生此回收时,垃圾收集器必须处理可能的终结器,并确保与该对象关联的任何内部JVM资源返回到此类资源的池中。Java堆转储是特定时间的Java堆的快照。
3.4.1.运行安装
3.4.1.1.下载
ftp://public.dhe.ibm.com/software/websphere/appserv/support/tools/HeapAnalyzer/ha456.jar
3.4.1.2.运行
命令: java -jar ha456.jar
File->Open 打开一个dump 文件,分析结果自动展示了
注:对于大内存来说,堆文件可能都几十个G,堆文件可能都生成不了,也是分析不出来的。可以根据具体需求配置Xmx的大小 java -Xmx4g -jar ha456.jar
3.4.2.分析
3.4.2.1.实例一
可以直接点位到最大的内存占据的堆树
该实例中涉及多线程,由于内存上升,发送越来越慢。堆积越来越多。生产者的数据持续接收,消费者无法发送数据。其中BlockingQueue转List,三个线程最后都有未处理完的ArrayList导致,内存溢出。
3.4.2.2.实例二
运行环境:
-Xms5m -Xmx5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/dev/dump
1)测试代码:
3)IBM分析结果
从分析结果中我们可以清晰的看到,Total size=5,762,360 bytes,远大于5M,因此导致的java堆内存溢出的主要原因在该类中。
3.4.2.3.其他场景分析
分析文件中存在一些集合,无法定位到具体的类,只能依据对代码的熟悉,进行定位。
如: