Java内存溢出OutOfMemoryError的产生与排查
在java的虚拟机异常中,有两个异常是大家比较关心的,一个是StackOverflowError,另一个是OutOfMemoryError。今天我们就来看看OutOfMemoryError是怎么产生的,以及如何去排查这个异常。
概念
要了解什么是OutOfMemoryError,我们可以直接看一下OutOfMemoryError的源码,在类上的英文注释很好的阐述了什么是OutOfMemoryError,翻译过来的意思是,由于内存不足,虚拟机没有可分配的内存了,垃圾回收器也不能释放更多的内存。在生产环境中,由于访问量过大,把内存吃满,会出现OutOfMemoryError的异常,小伙伴们如果没有经验的话,往往束手无策,到底是真的内存不够用了,还是自己的程序有问题,也不知道如何去排查这样的异常。
模拟OutOfMemoryError
在这里,我们写一段程序,来模拟一下OutOfMemoryError如何产生,我们创建一个List对象,然后向里边不停的添加1M的Byte,如下;
public static void main(String[] args) {
List<Byte[]> list = new ArrayList<>();
int i = 0;
try {
while (true) {
list.add(new Byte[1024 * 1024]);
i++;
}
} catch (Throwable e) {
e.printStackTrace();
System.out.println("执行了"+i+"次");
}
}
- 我们写了一个while(true)循环,每次都add一个1M的字节对象,1024*1024正好1M。
- 我们用i的值记录总共执行了几次。
- 如果这样不停的执行下去,不管你有多大的内存,都会被吃光的。
我们为了让程序运行时,快速的抛出OutOfMemoryError异常,可以在java的启动命令行增加启动参数,设置堆内存的初始值和最大值。这两个值在生产环境下,通常也是要配置的哦,要充分利用机器的内存嘛,如果不配置就会使用默认值。到时候由于内存不足向老板申请机器,可别挨骂哦~
那这两个参数怎么去加呢?
- -Xms ,-Xms设置初始堆内存的大小
- -Xmx, -Xmx设置最大堆内存的大小
通常情况下,这两个值设置成一样就可以了,总之,我们设置了堆内存的大小。我们在IDEA的启动配置中,统一设置堆内存为80M,如下;
好了~~我们运行一下,看看会不会抛出OutOfMemoryError异常吧
java.lang.OutOfMemoryError: Java heap space
at com.diancan.JavaOOMDemo.main(JavaOOMDemo.java:14)
执行了14次
执行了14次,抛出了OutOfMemoryError异常。但是,如果抛出这样一个异常,我们怎么去排查呢?就这一行日志也看不出什么来啊。
排查
说到排查,如果我们能够拿到异常时的内存快照,然后通过一些工具就可以了进行内存的分析了。那么我们怎么去拿到内存溢出时的快照呢?其实,JDK也为我们提供了这样的命令参数,我们来看一下吧,
- -XX:+HeapDumpOnOutOfMemoryError,从字面就可以很容易的理解,在发生OutOfMemoryError异常时,进行堆的Dump,这样就可以获取异常时的内存快照了。
- -XX:HeapDumpPath=D:\heap-dump\ ,这个也很好理解,就是配置HeapDump的路径,方便我们管理,这里我们配置为D:\heap-dump,当然你也可以根据自己的需要,定义为其他的目录。
注意,HeapDumpPath的目录一定要手动创建好,如果没有这个目录,Dump会失败的。
IDEA中的配置,如图:
我们再运行一下程序,看看是什么样子,
java.lang.OutOfMemoryError: Java heap space
Dumping heap to D:\heap-dump\java_pid24312.hprof ...
Heap dump file created [123468648 bytes in 0.141 secs]
java.lang.OutOfMemoryError: Java heap space
at com.diancan.JavaOOMDemo.main(JavaOOMDemo.java:14)
执行了14次
我们发现日志上面多了点东西,创建了一个文件,在D:\heap-dump\java_pid24312.hprof。这个文件就是我们的内存快照。那么问题来了,我们如何查看这个文件呢?直接打开是不行的,用写字板等也是不行的,那怎么办?其实也没那么复杂,使用JDK自带的jvisualvm就可以查看。
这里边有个小坑,如果大家用JDK8,可以在JDK的bin目录下找到jvisualvm.exe
,但是如果你使用的是JDK8以上的版本,就本示例中,使用的是JDK11,在bin目录下是找不到jvisualvm.exe
的。大家可以去visualvm的主页下载。
我们启动visualvm,进入到如下的页面,
然后,点击左上角的加载快照按钮,然后选择刚才我们Dump的文件,
我们重点看一下右侧中间的部分,
类的实例大小排序,可以看到,我们的Byte占了96.5%。详细的信息,我们可以点进去看,包括变量里存的内容,这样我们就可以很快的定位到内存溢出的位置,并且可以判断是真的内存不够了,还是我们的代码出了问题。
Java内存溢出OutOfMemoryError的产生与排查的更多相关文章
- java 内存溢出 栈溢出的原因与排查方法
1. 内存溢出的原因是什么? 内存溢出是由于没被引用的对象(垃圾)过多造成JVM没有及时回收,造成的内存溢出.如果出现这种现象可行代码排查: 一)是否App中的类中和引用变量过多使用了 ...
- Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结
最近老是遇见服务器内存溢出的问题,故在网上搜了搜,总结了一些java内存溢出的解决方式 java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生该错误的原因大都 ...
- [转]Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结
原文地址: http://outofmemory.cn/c/java-outOfMemoryError java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生 ...
- Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式
导致OutOfMemoryError异常的常见原因有以下几种: 内存中加载的数据量过于庞大,如一次从数据库取出过多数据: 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收: 代码中存在死循环 ...
- java内存溢出的解决思路
原文地址:https://www.cnblogs.com/200911/p/3965108.html 内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能 ...
- java内存溢出怎么解决
java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生该错误的原因大都出于以下原因:JVM内存过小.程序不严密,产生了过多的垃圾. 导致OutOfMemory ...
- [转]Java内存溢出详解及解决方案
原文地址:http://blog.csdn.net/xianmiao2009/article/details/49254391 内存溢出与数据库锁表的问题,可以说是开发人员的噩梦,一般的程序异常,总是 ...
- Java基础学习总结(30)——Java 内存溢出问题总结
Java中OutOfMemoryError(内存溢出)的三种情况及解决办法 相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题,这个问题曾困扰了我很长时间,随着解决各 ...
- 模拟Java内存溢出
本文通过修改虚拟机启动参数,来剖析常见的java内存溢出异常(基于jdk1.8). 修改虚拟机启动参数Java堆溢出虚拟机栈溢出方法区溢出本机直接内存溢出 修改虚拟机启动参数 这里我们使用的是ID ...
随机推荐
- Unity 游戏框架搭建 2019 (五十、五十一) 消息机制小结&MonoBehaviourSimplify 是框架?
我们花了 5 篇文章学习了消息机制的方方面面.并且完成了一个简易消息机制,之后集成到了我们的 MonoBehaviourSimplify 里. 现在 MonoBehaviourSimplify 有一点 ...
- [PHP学习教程 - 系统]004.通过ini_set()来设置系统属性(ini_set Method)
PHP原意:ini_set — 为一个系统配置项设置值 基本信息: string ini_set ( string $varname , string $newvalue). (说明:设置指定配置选项 ...
- Python中出现 SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 12-13: truncated \UXXXXXXXX escape
Python中出现 SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 12-13: t ...
- NIO 的非阻塞式网络通信
1.阻塞与非阻塞 ① 传统的 IO 流都是阻塞式的.也就是说,当一个线程调用 read() 或 write()时, 该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务. 因 ...
- JAVASE(十六) IO流 :File类、节点流、缓冲流、转换流、编码集、对象流
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1.File类型 1.1.File类的理解 File类是在java.io包下 File可以理解成一个文件 ...
- Java实现 LeetCode 605 种花问题(边界问题)
605. 种花问题 假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有.可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去. 给定一个花坛(表示为一个数组包含0和1,其中0表示没种 ...
- Java实现 LeetCode 565 数组嵌套(没有重复值的数组)
565. 数组嵌套 索引从0开始长度为N的数组A,包含0到N - 1的所有整数.找到并返回最大的集合S,S[i] = {A[i], A[A[i]], A[A[A[i]]], - }且遵守以下的规则. ...
- Java实现 LeetCode 290 单词规律
290. 单词规律 给定一种规律 pattern 和一个字符串 str ,判断 str 是否遵循相同的规律. 这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非 ...
- Java实现 蓝桥杯VIP 算法提高 3000米排名预测
算法提高 3000米排名预测 时间限制:1.0s 内存限制:256.0MB 问题描述 3000米长跑时,围观党们兴高采烈地预测着最后的排名.因为他们来自不同的班,对所有运动员不一定都了解,于是他们分别 ...
- Java实现 蓝桥杯VIP 算法提高 插入排序
算法提高 插入排序 时间限制:1.0s 内存限制:256.0MB 插入排序 问题描述 排序,顾名思义,是将若干个元素按其大小关系排出一个顺序.形式化描述如下:有n个元素a[1],a[2],-,a[ ...