简介

java.lang.OutOfMemoryError应该java应用程序中非常常见的一个的错误了。

那么OutOfMemoryError产生的原因是什么呢?我们怎么去查找相应的错误呢?一起来看看吧。

OutOfMemoryError

先看一下OutOfMemoryError的定义,OutOfMemoryError继承自

VirtualMachineError,它是Error的一种,表示的是应用程序无法处理的异常,一般情况下会导致虚拟机退出。

public class OutOfMemoryError extends VirtualMachineError {
@java.io.Serial
private static final long serialVersionUID = 8228564086184010517L; /**
* Constructs an {@code OutOfMemoryError} with no detail message.
*/
public OutOfMemoryError() {
super();
} /**
* Constructs an {@code OutOfMemoryError} with the specified
* detail message.
*
* @param s the detail message.
*/
public OutOfMemoryError(String s) {
super(s);
}
}

一般情形下,如果heap没有更多的空间来分配对象,就会抛出OutOfMemoryError。

还有一种情况是没有足够的native memory来加载java class。

在极少数情况下,如果花费大量时间进行垃圾回收并且只释放了很少的内存,也有可能引发java.lang.OutOfMemoryError。

如果发生OutOfMemoryError,同时会输出相应的stack trace信息。

下面我们分析一下各个不同的OutOfMemoryError。

java.lang.OutOfMemoryError: Java heap space

Java heap space表示的是新对象不能在java heap中分配。

如果遇到这种问题,第一个要想到的解决方法就是去看配置的heap大小是不是太小了。

当然,如果是一个一直都在运行的程序,突然间发生这种问题就要警惕了。因为有可能会存在潜在的内存泄露。需要进一步分析。

还有一种情况,如果java对象实现了finalize方法,那么该对象在垃圾回收的时候并不会立刻被回收。而是放到一个finalization队列中。

这个队列会由终结器守护线程来执行。如果终结器守护线程的执行速度比对象放入终结器队列中的速度要慢的话,就会导致java对象不能被及时回收。

如果应用程序创建了高优先级的线程,那么高优先级的线程将有可能会导致对象被放入finalization队列的速度比终结器守护线程的处理速度慢。

java.lang.OutOfMemoryError: GC Overhead limit exceeded

GC overhead limit exceeded表示的是GC一直都在运行,从而导致java程序本身执行非常慢。

如果一个java程序98%的时间都在做GC操作,但是只恢复了2%的heap空间,并且持续5次。那么java.lang.OutOfMemoryError将会被抛出。

可以使用下面的参数来关闭这个功能。

-XX:-UseGCOverheadLimit

java.lang.OutOfMemoryError: Requested array size exceeds VM limit

这个错误的意思是,要分配的array比heap size大。

比如说设置的最大heap大小是256M,但是分配了一个300M的数组,就会出现这个问题。

java.lang.OutOfMemoryError: Metaspace

从JDK8之后,Metaspace已经移到了java的本地内存空间中。如果Metaspace超出了限制的大小,那么java.lang.OutOfMemoryError也会抛出。

Metaspace的空间大小可以通过MaxMetaSpaceSize来设置。

java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?

当本地堆分配失败并且本地堆即将耗尽的时候就会报这个异常。

java.lang.OutOfMemoryError: Compressed class space

在64位的平台,对象指针可以用32位表示(对象指针压缩)。

对象指针压缩可以通过:

UseCompressedClassPointers

来启用,默认这个参数是开启的。

我们可以使用CompressedClassSpaceSize来设置指针压缩空间的大小。

注意,只有klass元信息是存放在CompressedClassSpaceSize设置的空间中的,而其他的元信息都是存放在Metaspace中的。

OutOfMemoryError: reason stack_trace_with_native_method

这个错误表示本地方法遇到分配失败。

遇到这种问题可能需要操作系统的本地调试工具来解决。

总结

本文介绍了OutOfMemoryError的不同种类,希望大家能够有所收获。

本文作者:flydean程序那些事

本文链接:http://www.flydean.com/jvm-outofmemoryerror-analysis/

本文来源:flydean的博客

欢迎关注我的公众号:程序那些事,更多精彩等着您!

troubleshoot之:分析OutOfMemoryError异常的更多相关文章

  1. OutOfMemoryError异常穷举

    本文内容的目的有两个:第一,通过代码验证Java虚拟机规范中描述的各个运行时区域存储的内容:第二,在工作中遇到实际的内存溢出异常时,能根据异常的信息快速判断是哪个区域的内存溢出,知道什么样的代码可能会 ...

  2. 了解OutOfMemoryError异常 - 深入Java虚拟机读后总结

    JVM中的异常发生 Java虚拟机规范中除了程序计数器外,其他几个运行时区域都有发生OutOfMemoryError异常的可能. 本章笔记通过代码来验证Java虚拟机规范中描述的各个运行时区域存储的内 ...

  3. JVM探秘2--详解内存溢出OutOfMemoryError异常

    JVM运行时内存被划分成多个区域,而除了程序计数器之外,其他几个区都会出现OutOfMemoryError异常,主要原因就是对应内存区域的内存不足以再分配内存,一般要么是内存泄漏了要么就是内存参数设置 ...

  4. OutOfMemoryError异常java内存泄漏(Memory Leak)和内存溢出(Memory Overflow)

    本篇文章理解源自于<深入理解java虚拟机>2.4章节 实战:OutOfMemoryError异常   在以下例子中,所有代码都可以抛出OutOfMemoryError异常,但是要区分到底 ...

  5. JVM --- OutOfMemoryError异常

    在Java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有可能发生OutOfMemoryError(OOM)异常. 1.Java堆溢出 Java堆用于存储对象实例,只要不断地创 ...

  6. 《深入理解java虚拟机》笔记(3)实战:OutOfMemoryError异常

    一.Java堆溢出 测试代码: /** * <p>Java堆异常测试</p> * <code>VM Args: -Xms20m -Xmx20m -XX:+HeapD ...

  7. 理解 OutOfMemoryError 异常

    OutOfMemoryError 异常应该可以算得上是一个非常棘手的问题.JAVA 的程序员不用像苦逼的 C 语言程序员手动地管理内存,JVM 帮助他们分配内存,释放内存.但是当遇到内存相关的问题,就 ...

  8. 3、实战:OutOfMemoryError异常

    目的:第一,通过代码验证Java虚拟机规范中描述的各个运行时区域存储的内容:第二,工作中遇到实际的内存溢出异常时,能根据异常的信息快速判断是哪个区域的内存溢出,知道什么样的代码可能会导致这些区域内存溢 ...

  9. 剖析Java OutOfMemoryError异常

    剖析Java OutOfMemoryError异常 在JVM中,除了程序计数器外,虚拟机内存中的其他几个运行时区域都有发生OutOfMemoryError异常的可能,本篇就来深入剖析一下各个区域出现O ...

随机推荐

  1. Python 100个样例代码【爆肝整理 建议收藏】

    本教程包括 62 个基础样例,12 个核心样例,26 个习惯用法.如果觉得还不错,欢迎转发.留言. 一. Python 基础 62 例 1 十转二 将十进制转换为二进制: >>> b ...

  2. Python协程之Gevent模块

    背景 进程是操作系统分配资源的最小单位,每个进程独享4G的内存地址空间,因此进程内数据是安全的,检查间的通信需要使用特定的方法.同理,正是因为进程是数据安全的,所以导致进程的切换是一个很麻烦效率不高的 ...

  3. 将音频文件转二进制分包存储到Redis(奇淫技巧操作)

    功能需求: 一.获取本地音频文件,进行解析成二进制数据音频流 二.将音频流转化成byte[]数组,按指定大小字节数进行分包 三.将音频流分成若干个包,以List列表形式缓存到redis数据库中 四.从 ...

  4. MySQL(三)视图

    视图:view,是一种有结构(有行有列)但是没有结果(结构中不真实的存放数据)的虚拟表,虚拟表的结构来源不是自己定义,而是从对应的基表中产生(视图的数据来源): 视图意义: 1.视图可以节省SQL语句 ...

  5. 一个startforresult的例子

    https://blog.csdn.net/qq_32521313/article/details/52451364

  6. 第37课 智能指针分析(指针特征操作符( -> 、 *)重载)

    1. 永恒的话题:内存泄漏 (1)动态申请堆空间,用完后不归还 (2)C++语言中没有垃圾回收的机制 (3)指针无法控制所指堆空间的生命周期------------指针是变量,可以指向内存堆空间,但是 ...

  7. lua 表

    最近在尝试配置 awesome WM,因此粗略地学习了一下 lua . 在学习过程中,我完全被表表在 lua 中的应用所镇住了. 表在 lua 中真的是无处不在:首先,它可以作为字典和数组来用:此外, ...

  8. Java容器学习之ArrayList

    一.概述 ArrayList是java中十分常用的集合类,继承于AbstractList,并实现了List.RandomAccess.Cloneable和Serializable接口.ArrayLis ...

  9. string类型 C++

    (C++递归预习到了string类型,这个是处理字符串的一个非常好用的东西,在C里面没有.今天来学习一下) 顺便推荐一个很不错的网站:http://c.biancheng.net/view/400.h ...

  10. ABAP 动态备份自建表数据到新表(自建表有数据的情况下要改字段长度或者其他)

    当abaper开发好一个程序给用户使用一段时间后,发现某个字段的长度需要修改,但数据库表中已经存在很多数据,冒然直接改表字段可能会导致数据丢失,这种问题的后果可能非常严重. 所以我想到先复制出一个新表 ...