美文网首页Java虚拟机
OutOfMemoryError异常处理

OutOfMemoryError异常处理

作者: 暮想sun | 来源:发表于2020-01-11 17:08 被阅读0次

    Java虚拟机的运行时数据区域,除了程序计数器之外,都可能会出现outOfMemoryError异常。

    一、Java堆溢出

    -Xmx:堆最大值 -Xms:堆最小值

    Java堆用于存储对象实例,只要不断地创建对象,并且保证GC Roots到对象之间有可达的路径来避免垃圾回收机制清除这些对象,那么在对象数量达到最大堆的容量限制后就会产生内存溢出异常。
    例:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError


    解决方法:

    1.基于内存调整来改变堆区内存大小以便能够存储更多的对象,但堆内存受到物理内存的限制.
    2.从代码上检查是否存在某些对象的生命周期过长、持有状态时间过长的情况,尝试减少程序在运行期的内存消耗。

    二、虚拟机栈和本地方法栈溢出

    栈容量只有-Xss参数设定。

    如果线程请求的栈深度大于虚拟机所允许的最大深度,抛出StackOverflowError异常。
    如果虚拟机在扩展栈时无法申请到足够的内存空间,抛出OutOfMemoryError异常。

    单线程环境下,无论是栈帧太大还是虚拟机栈容量太小,当内存无法分配的时候,虚拟机抛出的都是StackOverflowError异常。
    例:-Xss128k



    解决方案:
    1.从内存大小上,增加每个线程的虚拟机栈大小
    2.从Java程序上无疑就是检查是否出现方法的不合理递归调用,从而减少栈帧的创建和及时的回收。

    多线程环境下,每个线程分配到的栈容量越大,可以建立的线程数量越少,建立线程时越容易把剩下的内存耗尽。
    例:-Xss2M



    解决方案:
    1.减少线程数
    2.减少最大堆和减少栈容量来换取更多线程。

    三、方法区和运行时常量池溢出

    -XX:PermSize方法区容量大小 -XX:MaxPermSize方法区最大容量

    JDK1.6运行时常量池在方法区,-XX:PermSize=10M -XX:MaxPermSize=10M OutOfMemoryError:PermGen Space
    JDK1.7运行时常量池在堆内,-Xmx20M -Xms20M OutOfMemoryError:Java Heap Space
    自JDK1.7起,字符串常量池从永久代移至Java堆。

    JDK8之后的元空间设置参数:

    -XX:MaxMetaspaceSize:设置元空间最大值,默认是-1,不限制,或者说只受本地内存大小限制。
    -XX:MetaspaceSize:元空间初始空间大小,以字节为单位,达到该值就会触发垃圾收集进行类型卸载,同时收集器会对该值进行调整:如果释放了大量的空间,就适当减低该值,如果释放空间很少,那么在不超过XX:MaxMetaspaceSize的情况下可以适当提高。
    -XX:MinMetaspaceFreeRatio:在垃圾收集之后控制最小的元空间剩余容量的百分比,可减少因为元空间不足导致的垃圾收集的频率。

    四、本机直接内存溢出

    -XX:MaxDirectMemorySize最大直接内存容量。不指定,默认与Java堆最大值一样。

    由DirectMemory导致的内存溢出,明显的特征是Heap Dump文件中不会看到明显的异常,如果发现OOM之后的Dump文件很小,而程序中有直接或间接使用了NIO。


    相关文章

      网友评论

        本文标题:OutOfMemoryError异常处理

        本文链接:https://www.haomeiwen.com/subject/kazvactx.html