•   欢迎来到21NN网.
  •   请记住本站网址www.21nn.cn

Java非常之OutOfMemoryError的解决方法【JAVA教程】,Java异常

摘要: 本篇文章给人人带来的内容是关于Java非常之OutOfMemoryError的处理要领,有肯定的参考价值,有须要的朋侪能够参考一下,愿望对你有所协助。在Java虚拟机范例形貌中,除了顺序计数器...
本篇文章给人人带来的内容是关于Java非常之OutOfMemoryError的处理要领,有肯定的参考价值,有须要的朋侪能够参考一下,愿望对你有所协助。

在Java虚拟机范例形貌中,除了顺序计数器外,虚拟机内存的其他几个运转地区都有发作 OOM 非常的能够。在这里,用代码考证各个运转时地区存储的内容并议论该如何举行处置惩罚。

Java堆溢出

Java 堆用于存储对象实例,只需不停竖立对象,而且保证 GC Roots 到对象之间有可达门路来防止垃圾接纳机制消灭这些对象,那末对象数目到达最大堆的容量限定以后就会发生内存溢出非常。

非常再现

代码采纳以下虚拟机参数:

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

如许 Java 堆的大小将被限定为20 MB 且不可拓展。经由过程参数 -XX:+HeapDumpOnOutOfMemoryError 能够让虚拟机在涌现内存溢出非常时 Dump 出当前的内存堆转储快照以便时刻举行剖析。

采纳以下代码举行考证:

public class HeapOOM {
    static class OOMObject {
    }
    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<OOMObject>();

        while (true) {
            list.add(new OOMObject());
        }
    }
}

运转效果:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid3460.hprof ...
Heap dump file created [28199779 bytes in 0.237 secs]

处理要领

Java 堆内存的 OOM 非常是现实运用中常见的内存溢出非常状况,涌现时往往会紧跟着提醒“Java heap space”。

要处理这个地区的非常,平常的手腕是先经由过程内存映像剖析东西,比方 MAT ,确认究竟是涌现了内存走漏照样内存溢出。

假如是内存走漏,能够进一步经由过程东西检察走漏对象到 GC Roots 的援用链,找到走漏对象是经由过程如何的门路和 GC Roots 相干联并致使垃圾收集器没法自动接纳它们所占的空间。

假如不是内存走漏,换而言之,内存中的对象确切另有必要存在世,那末就应当搜检虚拟机的堆参数,与机械物理内存对照看是不是还能够调大。从代码层面上看,是不是存在某些对象生命周期太长、持有状况时候太长的状况,尝试削减顺序运转时期的内存斲丧。

虚拟机栈和当地要领栈溢出

由于在 HotSpot 虚拟机中并不辨别虚拟机栈或许当地要领栈,因而关于 HotSpot 而言,虽然 -Xoss 参数存在,然则现实上是无效的,栈容量只由 -Xss 参数设定。

非常再现

在单线程下,代码采纳以下的虚拟机参数:

-Xss128k

运用该参数减小栈容量,运用以下代码复现非常:

public class JavaVMStackSOF {

    private int stackLength = 1;

    public void stackLeak() {
        stackLength++;
        stackLeak();
    }

    public static void main(String[] args) throws Throwable {
        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Throwable e) {
            System.out.println("stack length:" + oom.stackLength);
            throw e;
        }
    }
}

处理要领

假如运用虚拟机默许参数,栈深度在大多数状况下(由于每一个要领压入栈的帧大小并非一样的,所以只能说在大多数状况下)到达1000 ~ 2000 完整没有问题,关于一般的要领挪用(包含递归),这个深度应当完整充足。

然则,假如是由于竖立过量的线程致使内存溢出,在不能削减线程数或许替换64位虚拟机的状况下,就只能经由过程削减最大堆和削减栈容量来调换更多的线程。

本机直接内存溢出

DirectMemory 容量能够经由过程 -XX :MaxDirectMemorySize 指定,假如不指定,则默许与Java最大堆一样。

非常再现

运用以下虚拟机参数:

-Xmx20M -XX:MaxDirectMemorySize=10M

运用以下代码重现非常:

public class DirectMemoryOOM {
    private static final int _1MB = 1024 * 1024;
    public static void main(String[] args) throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredFields()[0];
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        while (true) {
            unsafe.allocateMemory(_1MB);//直接请求分派内存
        }
    }
}

处理要领

由 DirectMemory 致使的内存溢出,一个显著的特性就是在Heap Dump 文件中不会瞥见显著的非常。

假如发明 OOM 以后Dump文件很小,而顺序中又直接或许间接运用了NIO ,那末就能够斟酌搜检一下是不是是这方面的缘由。

以上就是Java非常之OutOfMemoryError的处理要领的细致内容,更多请关注ki4网别的相干文章!

分享到:

发表评论

评论列表

还没有评论,快来说点什么吧~

公众号二维码

微信公众号