在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的产生与排查的更多相关文章

  1. java 内存溢出 栈溢出的原因与排查方法

     1. 内存溢出的原因是什么?        内存溢出是由于没被引用的对象(垃圾)过多造成JVM没有及时回收,造成的内存溢出.如果出现这种现象可行代码排查: 一)是否App中的类中和引用变量过多使用了 ...

  2. Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结

    最近老是遇见服务器内存溢出的问题,故在网上搜了搜,总结了一些java内存溢出的解决方式 java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生该错误的原因大都 ...

  3. [转]Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结

    原文地址: http://outofmemory.cn/c/java-outOfMemoryError java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生 ...

  4. Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式

    导致OutOfMemoryError异常的常见原因有以下几种: 内存中加载的数据量过于庞大,如一次从数据库取出过多数据: 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收: 代码中存在死循环 ...

  5. java内存溢出的解决思路

    原文地址:https://www.cnblogs.com/200911/p/3965108.html 内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能 ...

  6. java内存溢出怎么解决

    java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生该错误的原因大都出于以下原因:JVM内存过小.程序不严密,产生了过多的垃圾. 导致OutOfMemory ...

  7. [转]Java内存溢出详解及解决方案

    原文地址:http://blog.csdn.net/xianmiao2009/article/details/49254391 内存溢出与数据库锁表的问题,可以说是开发人员的噩梦,一般的程序异常,总是 ...

  8. Java基础学习总结(30)——Java 内存溢出问题总结

    Java中OutOfMemoryError(内存溢出)的三种情况及解决办法 相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题,这个问题曾困扰了我很长时间,随着解决各 ...

  9. 模拟Java内存溢出

    本文通过修改虚拟机启动参数,来剖析常见的java内存溢出异常(基于jdk1.8). 修改虚拟机启动参数Java堆溢出虚拟机栈溢出方法区溢出本机直接内存溢出 修改虚拟机启动参数   这里我们使用的是ID ...

随机推荐

  1. 一文带你学会基于SpringAop实现操作日志的记录

    前言 大家好,这里是经典鸡翅,今天给大家带来一篇基于SpringAop实现的操作日志记录的解决的方案.大家可能会说,切,操作日志记录这么简单的东西,老生常谈了.不! 网上的操作日志一般就是记录操作人, ...

  2. Robot Framework(13)- RF 循环的详细使用

    如果你还想从头学起Robot Framework,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1770899.html 前言 RF用   ...

  3. [Python基础]006.IO操作

    IO操作 输入输出 print raw_input input 文件 打开文件 关闭文件 读文件 写文件 文件指针 实例 输入输出 输入输出方法都是Python的内建函数,并且不需要导入任何的包就可以 ...

  4. Web缓存欺骗

    该漏洞主要是cdn安全配置的问题,cdn主要存储以下文件,加快访问速度 class, css, jar, js, jpg, jpeg, gif, ico, png, bmp, pict, csv, d ...

  5. jchdl - RTL Module

    https://mp.weixin.qq.com/s/Sr4ffU4TPPoUJpdInwWd6w ​​ jchdl Module类在概念上对应Verilog的module,作为所有用户自定义模块的父 ...

  6. Chisel3 - util - MixedVec

    https://mp.weixin.qq.com/s/mO648yx4_ZRedXSWX4Gj2g   可以容纳不同类型的变量的向量.   参考链接: https://github.com/freec ...

  7. HashMap1.7和1.8,红黑树原理!

    jdk 1.7 概述 HashMap基于Map接口实现,元素以键值对的方式存储,并允许使用null键和null值,但只能有一个键作为null,因为key不允许重复,另外HashMap不能保证放入元素的 ...

  8. Java实现洛谷 P1072 Hankson 的趣味题

    P1072 Hankson 的趣味题 输入输出样例 输入 2 41 1 96 288 95 1 37 1776 输出 6 2 PS: 通过辗转相除法的推导 import java.util.*; cl ...

  9. Java实现 蓝桥杯 算法训练 排序

    算法训练 排序 时间限制:1.0s 内存限制:512.0MB 问题描述 编写一个程序,输入3个整数,然后程序将对这三个整数按照从大到小进行排列. 输入格式:输入只有一行,即三个整数,中间用空格隔开. ...

  10. Java实现 LeetCode 381 O(1) 时间插入、删除和获取随机元素 - 允许重复

    381. O(1) 时间插入.删除和获取随机元素 - 允许重复 设计一个支持在平均 时间复杂度 O(1) 下, 执行以下操作的数据结构. 注意: 允许出现重复元素. insert(val):向集合中插 ...