网站首页 > 技术文章 正文
一、名词解释
- 内存泄漏(memory leak)含义:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。
- 内存溢出(out of memory):简称OOM含义:程序申请内存时,没有足够的内存分配给使用者
注:内存泄漏的堆积最终会导致内存溢出
二、OOM常见报错信息
常见报错有下面2类:
- java.lang.OutOfMemoryError: Java heap spacejava堆空间不足,一般是堆内存设置过小 或 堆空间的对象太多,不能被GC清除
- java.lang.OutOfMemoryError: GC overhead limit exceeded如果Java进程花费98%以上的时间执行GC,并且每次只有不到2%的堆被恢复,则JVM抛出此错误。想象一下,如果不抛异常,再进行下去的话,系统就只能一直GC中,还有能力为你的服务吗?
三、模拟OOM
为了便于复现,我们先设置jvm参数:
-Xms5m -Xmx5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=E:\JAVA\dump
-Xms5m :堆初始内存(5m便于复现OOM)
-Xmx5m :堆最大内存(5m便于复现OOM)
-XX:+HeapDumpOnOutOfMemoryError:当JVM发生OOM时,自动生成DUMP文件(.hprof)
-XX:HeapDumpPath=E:\JAVA\dump :发生oom时,生成.hprof文件存放地址
编写程序,制造大量对象放入集合中:
private static class MyOOM {
}
public static void main(String[] args) {
List<MyOOM> list = new ArrayList<>();
while (true) {
list.add(new MyOOM());
}
}
运行结果如下:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to E:\JAVA\dump\java_pid2892.hprof ...
Heap dump file created [9507297 bytes in 0.068 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.abao.demo.Demo.main(Demo.java:22)
四、分析与改进措施
一般解决OOM有如下几种方法:
1、增大堆空间
既然堆内存少了,那就增加堆内存即可。但是再大的内存也会有用尽的时候,因此此方法治标不治本。
2、找到占用内存大的地方,优化代码
怎么定位呢?通过jvm生成的dump文件定位。
运行结果中已经表明,当发生OOM时,堆栈信息的文件的存放路径了。这里我们使用工具打开java_pid2892.hprof。常用工具有 jvisualvm(jdk自带)、MAT、arthas(阿里的工具)等。
我们选择jvisualvm(cmd窗口中输入 jvisualvm就会自己打开该工具)
在概要-堆转储上的线程 中查看发生OOM的地方,点击进入看详情(此处可以看到发生OOM在哪一行代码)
结合上下2张图可以看出来,当向ArrayList中插入第240098个MyOOM对象时出现内存溢出了。
因此我们可以看看整个jvm中对象信息,可以看到此对象产生的数量太多了,占用堆空间最大。
3、怎么改
既然找到哪一行代码发生的问题,以及是哪一个对象了。便可以适当清除集合,比如下方代码:
public static void main(String[] args) {
List<MyOOM> list = new ArrayList<>();
while (true) {
list.add(new MyOOM());
if (一定的业务条件){
list.clear();// 清除集合中对象的引用
}
}
}
综上,只要我们设置合理的堆栈大小,再配合一定的代码优化便可一定程度上解决OOM,让程序更健壮。
猜你喜欢
- 2024-10-12 SpringBoot执行jar报错java.lang.OutOfMemoryError_指定内存大小
- 2024-10-12 几种内存溢出(内存溢出类型)
- 2024-10-12 JVM优化:实战OutOfMemoryError异常
- 2024-10-12 JVM 在遇到OOM(OutOfMemoryError)时生成Dump文件的三种方式
- 2024-10-12 线上故障排查全套路,总有一款适合你
- 2024-10-12 面试被问到“零拷贝”!你真的理解吗?
- 2024-10-12 面试夺命三问之《内存溢出和逃逸分析》
- 2024-10-12 阿里面试官:Exception和Error有什么区别?
- 2024-10-12 Eclipse运行大量文件异常OutOfMemoryError: GC overhead limit
- 2024-10-12 记一次线上内存异常排查实战(线上内存泄漏如何定位)
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)