内存溢出在开发中或者线上出现的概率很高,造成的直接结果是系统运行缓慢,或者直接宕机。
在这里模拟下内存溢出的情况以防患于线上出现内存溢出要如何排查问题,线上出问题需要生成一个快照(hprof文件),在本地查看问题。
其他工具调试如阿里的Arthas、MAT、jvisualvm、JProfiler。
1,准备一个可以出现内存溢出的代码:
public class TestOOM {
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
while(true){
list.add(new Object());
}
}
}
2,在IDEA中配置VM参数【-Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:\jvmtest】
说明:
-Xms 为jvm启动时分配的内存,比如-Xms2m,表示分配2M。
-Xmx 为jvm运行过程中分配的最大内存,比如-Xmx4m,表示jvm进程最多只能够占用4M内存。
-XX:+HeapDumpOnOutOfMemoryError 表示出现OutOfMemoryError异常时,记录快照。
-XX:HeapDumpPath 表示快照的存储位置(这里可以设置文件名字,也可以不设置),不设置名字它会自己生成的。
执行后,会抛出如下异常
3,使用jvisualvm查看内存快照,使用jvisualvm.exe来打开生成的hprof文件
4,点击main线程进入(当前哪个类上出现类内存溢出)
5,看到ArrayList,点进去
可以看得到ArrayList的存储大小。在点击到elementData看看里面存储的什么元素?看得出是TestOOMA$OOMObject这个对象,也就是上面例子中的对象。
注意:集合中存储的对象个数,或者说集合长度。
6,右键单击,在实例视图中显示
类实例视图页面可以查看类的属性信息、值和引用信息,最重要的是类的引用信息。
提示:类xxx.TestOO没有实例,只有静态方法。
7,在类视图中也可以看见这个对象在飙升,占了实例总数的93%。
也就分析出,内存溢出的原因就是因为疯狂的创建对象造成的。
如何在启动的时候设置虚拟机参数?
如何获取内存快照?
如何通过jvisualvm加载内存快照?
如何分析找到在哪个类中哪个线程中出现了内存溢出?
如何查看某个实例的数量?
如何搜索某个类实例的数量?
在mat中打开dump文件,查看对象占用内存情况
概要面板,类面板,实例数面板。
错误信息1:
Error occurred during initialization of VM
GC triggered before VM initialization completed. Try increasing NewSize, current value 1536K.
原因:若设置初始内存过小得让gc无法触发,比如-Xms1200k,则会报错。估算gc需要2500K的内存。
错误信息2:
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=10m; support was removed in 8.0
JVM8.0已经没有持久代,若设置则会警告。