面试经常被问到,OutOfMemoryError什么时候会出现,在网上找了很多资料,记录下学习笔记。
制造一个OutOfMemoryError场景
堆溢出
如下代码,让程序一直往list集合里面添加数据。
package com.batman.jvm;
import java.util.ArrayList;
import java.util.List;
public class OutOfMemory01 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
while (true) {
list.add(new String("test"));
}
}
}
方式一:使用java命令生成
javac -d . OutOfMemory01.java
java -Xmx5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./gc.hprof com.batman.jvm.OutOfMemory01
运行以上指令会出现一下结果。
java.lang.OutOfMemoryError: Java heap space
Dumping heap to ./gc.hprof ...
Heap dump file created [8059647 bytes in 0.044 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:261)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
at java.util.ArrayList.add(ArrayList.java:458)
at com.batman.jvm.OutOfMemory01.main(OutOfMemory01.java:12)
提示: javac -d . 「java文件名」 这个带着包名编译,从而你运行的时候也需要上包名。
参数解释:
-Xmx5m :指定最大堆内存
-XX:+HeapDumpOnOutOfMemoryError: 参数表示当JVM发生OOM时,自动生成DUMP文件
-XX:HeapDumpPath= 目 录 参 数 表 示 生 成 D U M P 文 件 的 路 径 , 也 可 以 指 定 文 件 名 称 , 例 如 : − X X : H e a p D u m p P a t h = {目录}参数表示生成DUMP文件的路径,也可以指定文件名称,例如:-XX:HeapDumpPath= 目录参数表示生成DUMP文件的路径,也可以指定文件名称,例如:−XX:HeapDumpPath={目录}/java_heapdump.hprof。如果不指定文件名,默认为:java_
这个时候执行下ls
命令可以看到已经生成gc.hprof
文件,接下来就可以准备mat工具分析这个文件。
方式二:使用神奇IDEA工具
配置你这个类的VM option
,加上-Xmx5m -XX:+HeapDumpOnOutOfMemoryError
这个生成文件的位置是在你的项目的根路径下,我cd
到我的项目跟路径下面ls
可以看到一个dump文件java_pid78380.hprof
。
安装mat
mat下载地址:https://www.eclipse.org/mat/downloads.php
下载你对应的版本即可,之后解压,点击运行文件即可。
启动如果报错,配置下jdk , /Applications/mat.app/Contents/Eclipse/MemoryAnalyzer.ini
-startup
../Eclipse/plugins/org.eclipse.equinox.launcher_1.5.0.v20180512-1130.jar
--launcher.library
../Eclipse/plugins/org.eclipse.equinox.launcher.cocoa.macosx.x86_64_1.1.700.v20180518-1200
-vm
/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/bin
-data
/Users/XXXX/mat-log
-vmargs
-Xmx1024m
-Dorg.eclipse.swt.internal.carbon.smallFonts
-XstartOnFirstThread
导入dump文件
执行如图下操作
选择Leak Suspects Report
,自动的生成可能出现堆溢出的报表结果,点击finish
。
说你的main函数有一个变量占有93%的堆内存。点击Details
查看详情
下面的结果表明,是ArrayList出现了问题,我看了这个Domainator Tree
,出现了test
这个值,可以定位到我们哪行代码出现了问题。
以上只是对堆溢出场景的一个简单分析流程。后续会慢慢晚上JVM
的学习记录。最后送上一句鸡汤。
风只会吹灭蜡烛,但会让火炉越吹越旺。