乐趣区

关于java:troubleshoot之分析OutOfMemoryError异常

简介

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 的博客

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

退出移动版