Java中的OOM问题
OOM是什么
OOM全称"OutOfMemory",既内存溢出。我们知道,Java中的对象是在堆(heap)上创建的,当堆内存不足以为新创建的对象分配空间时,就会产生OutOfMemoryError。
为什么会产生OOM
由于GC机制的存在,Java程序员不需要过多地关注内存的分配与回收,GC通过“可达性分析”来判断一个对象是否需要被回收。
可达性分析:GC首先确定一组GC Root节点(通常是一些全局性的元素,例如JVM持有的对象),然后根据GC Root是否持有指向某个对象的引用或引用链来判断这个对象是否“可达”。
GC会回收大部分的无用对象,当发生OOM时,通常会有两种情况:
- JVM的堆内存真的不足了
- 代码问题
如果是堆内存不足,只需要简单地扩大堆内存就可以了。但是绝大多数情况下,OOM都是由代码问题引发的,也就是说很多本该被回收的对象没有被回收,导致堆内存不足。
如何处理OOM问题
处理OOM问题的关键在于拿到Heap Dump(堆转储文件),它保存了某一时刻JVM堆中对象对内存的使用情况。获取Heap Dump文件可以通过:
- 启动程序前,添加JVM参数
-XX:+HeapDumpOnOutOfMemoryError
该参数的含义是:当发生OOM时,生成Heap Dump文件。
- 程序运行过程中, 通过jmap获取。首先通过jps获取到Java进程的pid,然后通过jmap输出Dump文件
jmap -dump:live,format=b,file=<filepath> <pid>
其中filepath是生成dump文件的位置,pid是你想要分析的Java进程的pid。
拿到dump文件后,就可以通过一些图形化工具来进行分析了。常用的图形化工具有visual VM、MAT、JProfiler等。
举个栗子
- 首先我们编写一个程序,并设置JVM最大堆内存为128M,使其在一段时间后发生OOM,并使用vitual VM进行简单的分析。
-Xmx128m
import java.util.ArrayList;
import java.util.List;
public class OOMExample {
public static void main(String[] args) throws InterruptedException {
List<byte[]> list = new ArrayList<>();
for(int i=0;i<128;i++){
list.add(new byte[1024*1024]);
Thread.sleep(500);
}
}
}
- 运行期间我们通过在命令行中输入jps可以获取到当前进程pid。也可以通过vitual VM直接查看(我这里是分开两次运行截的图所以pid不一致)。


- 通过vitual VM我们可以看到程序的实时运行情况,正常情况下程序的内存曲线应该是波浪形,我们的程序即将发生OOM。

- 通过jmap获取dump文件
jmap -dump:live,format=b,file="/12844.hprof" 12844
- 使用vitual VM查看dump文件

很明显可以看到byte数组占据了绝大部分的内存,这与我们的预想一致。实际场景中,OOM的对象引用关系要比这复杂得多,具体问题具体分析,如何快速发现问题代码,也是一个难题,本文权当抛砖引玉。
Java中的OOM问题的更多相关文章
- Java中关于OOM的场景及解决方法
原文地址:http://developer.51cto.com/art/201112/305696.htm 1.OOM for Heap=>例如:java.lang.OutOfMemoryErr ...
- Java中关于OOM的场景及解决方法(转)
http://developer.51cto.com/art/201112/305696.htm 1.OOM for Heap=>例如:java.lang.OutOfMemoryError: J ...
- [转载] java中关于OOM的场景及解决方法
1.OOM for Heap=>例如:java.lang.OutOfMemoryError: Java heapspace[分析] 此OOM是由于JVM中heap的最大值不满足需要,将设置hea ...
- java中OOM错误解析(面试可以聊的东西)
嗯,生活加油鸭.... 实习中遇到OOM错误 GC overhead limit exceeded 问题,所以整理一下OOM异常问题: 先看一下“阿里的开发手册”对OOM的描述: OOM,全称“Out ...
- Java中四种引用:强、软、弱、虚引用
这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...
- Java中的字符串常量池
ava中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new ...
- 理论篇-Java中一些零碎的知识点
1. Java中length,length方法,size方法区别 length属性:用于获取数组长度. length方法:用于获取字符串长度. size方法:用于获取泛型集合有多少个元素. 2. is ...
- java中引用的概念
强引用(StrongReference) 强引用就是指在程序代码之中普遍存在的,比如下面这段代码中的object和str都是强引用: 1 2 Object object = new Object(); ...
- JAVA中的引用
关于值类型和引用类型的话题,C++.JAVA.python.go.C#等等高级语言都有相关的概念,只要理解了其底层工作原理,可以说即使是不同的语言,在面试学习工作实践中都可以信手拈来(不要太纠集语言) ...
随机推荐
- postgre安装和使用(R&Python)
安装postgre http://helianthus-code.lofter.com/post/1dfe03e0_1c68233aa 这里选C更好 这里口令密码输入就是黑的 我装的时候反复报错,查了 ...
- Transformers 快速入门 | 一
作者|huggingface 编译|VK 来源|Github 理念 Transformers是一个为NLP的研究人员寻求使用/研究/扩展大型Transformers模型的库. 该库的设计有两个强烈的目 ...
- Ubuntu文件(文件夹)创建(删除)
创建 创建文件: touch a.txt创建文件夹: mkdir NewFolderName 删除 删除文件: rm a.txt删除文件夹: rmdir FolderName删除带有文件的文件夹: r ...
- 并发——抽象队列同步器AQS的实现原理
一.前言 这段时间在研究Java并发相关的内容,一段时间下来算是小有收获了.ReentrantLock是Java并发中的重要部分,所以也是我的首要研究对象,在学习它的过程中,我发现它是基于抽象队列 ...
- 使用Spring实例化Bean的方法以及Bean取别名
一.通过构造方法实例化Bean bean中加构造方法 public class Bean1 { public Bean1() { System.out.println("Bean1构造方法. ...
- HTML+CSS:css定位详解之相对定位、绝对定位和固定定位
相对定位 如果想为元素设置层模型中的相对定位,需要设置position:relative;,它还是会占用该元素在文档中初始的页面空间,通过left.right.top.bottom属性确定元素在正常文 ...
- LeetCode | 第180场周赛--5356矩阵中的幸运数
给你一个 m * n 的矩阵,矩阵中的数字 各不相同 .请你按 任意 顺序返回矩阵中的所有幸运数. 幸运数是指矩阵中满足同时下列两个条件的元素: 在同一行的所有元素中最小 在同一列的所有元素中最大 示 ...
- MyBatis(三):核心配置文件的重要配置-Log
本文是按照狂神说的教学视频学习的笔记,强力推荐,教学深入浅出1便就懂!b站搜索狂神说即可 https://space.bilibili.com/95256449?spm_id_from=333.788 ...
- 搭建DVWA Web渗透测试靶场
文章更新于:2020-04-13 按照惯例,需要的文件附上链接放在文首. 文件名:DVWA-1.9-2020.zip 文件大小:1.3 M 文件说明:这个是新版 v1.9 (其实是 v1.10开发版) ...
- (js描述的)数据结构[树结构1.2](12)
1.先序遍历 2.中序遍历 3.后序遍历 4.递归调用栈详解: 详细见: https://zhuanlan.zhihu.com/p/24291978 5.删除节点操作分析: 5.代码封装 //封装二叉 ...