OutOfMemoryError异常----Java堆溢出

在Java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(下面都叫OOM)异常的肯能,下面就通过一些实例来验证异常发生的场景。 在下面举的例子中,在注释中会设定一些虚拟机的参数,在”VM Args”后边,如果你是用控制台命令来执行的程序,直接把这些参数放到Java命令之后就行,如果用的开发工具,Eclipse IDE,才Debug/Run页签中设置。

Java堆溢出


堆是用来存储对象实例的,当我们不断的创建对象,并且保证GC Roots和对象之间有相互的引用关系(GC Roots指垃圾回收器的对象,GC会手机那些不是GC Roots且没有被GC Roots引用的对象),当对象数量达到最大堆的容量的时候,就会产生内存溢出异常。

/**
 * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 * @author Administrator
 *
 */
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堆的大小为20MB,不可扩展(将堆的最小值-Xms 参数与最大值-Xmx参数设置为一样就可以避免堆自动扩展),通过-XX:+HeapDumpOnOutOfMemoryError当虚拟机出现内存溢出的时候Dump出当前的内存堆转储快照以便后边进行分析。运行结果如下:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid5504.hprof ...
Heap dump file created [27872304 bytes in 0.150 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2245)
    at java.util.Arrays.copyOf(Arrays.java:2219)
    at java.util.ArrayList.grow(ArrayList.java:242)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:216)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)
    at java.util.ArrayList.add(ArrayList.java:440)
    at test.HeapOOM.main(HeapOOM.java:20)

刷新项目你就可以看到快照文件,可以用Eclipse Memory Analyzer来打开并进行分析。确定是Memory Leak,还是Memory Overflow。 处理思路:如果是内存泄漏,通过工具进一步查看泄漏对象到GC Roots的引用链,找到泄漏对象是如何和GC Roots相关联并导致垃圾回收器无法自动回收这些对象的。后边就可以判断产生内存溢出的代码的位置。 如果不存在内存泄漏问题,检查虚拟机的堆参数(-Xms -Xmx)跟物理机器对比是否还可以调大,在代码层面上看看是否存在某些对象生命周期过长、持有状态时间过长的情况。减少程序运行期间的内存消耗。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏服务端技术杂谈

JAVA NIO内存泄漏

前言 写NIO程序时,经常使用ByteBuffer来读取写入数据,那使用ByteBuffer.allocate()还是ByteBuffer.allocateDi...

37380
来自专栏蓝天

HDFS块文件和存放目录的关系

详情请参见DatanodeUtil.java中的函数idToBlockDir(File root, long blockId)。 如果block文件没有放在...

6700
来自专栏MySQL

JVM难学?那是因为你没认真看完这篇文章

JAVA程序运行与虚拟机之上,运行时需要内存空间。虚拟机执行JAVA程序的过程中会把它管理的内存划分为不同的数据区域方便管理。

13200
来自专栏Java架构

JVM难学?那是因为你没认真看完这篇文章

JAVA程序运行与虚拟机之上,运行时需要内存空间。虚拟机执行JAVA程序的过程中会把它管理的内存划分为不同的数据区域方便管理。

9220
来自专栏JAVA烂猪皮

JVM难学?那是因为你没认真看完这篇文章

JAVA程序运行与虚拟机之上,运行时需要内存空间。虚拟机执行JAVA程序的过程中会把它管理的内存划分为不同的数据区域方便管理。

11830
来自专栏JavaEE

spring及springboot整合redis前言:一、整合前提:二、spring整合redis:三、springboot整合redis:总结:

redis是一种nosql数据库,以<key,value>的形式存储数据,其速度相比于MySQL之类的数据库,相当于内存读写与硬盘读写的差别,所以常常用作缓存。...

10230
来自专栏Android相关

Java线程池---ThreadPoolExecutor中的ctl变量

ThreadPoolExecutor中有一个控制状态的属性叫ctl,它是一个AtomicInteger类型的变量,它包含两个概念:

19340
来自专栏Spark学习技巧

spark调优系列之内存和GC调优

本文基于spark1.6讲解。 一,基本概述 调优内存的使用主要有三个方面的考虑:对象的内存占用量(你可能希望整个数据集都适合内存),访问这些数据的开销,垃圾...

1.1K90
来自专栏眯眯眼猫头鹰的小树杈

Dubbo AbstractRegistry源码阅读

最近因为工作需要在学习Dubbo的各种机制。其中深入学习了一下AbstractRegistry的实现机制。在此根据Dubbo源码对其实现进行一个总结。

21820
来自专栏JAVA烂猪皮

JVM难学?那是因为你没认真看完这篇文章

JAVA程序运行与虚拟机之上,运行时需要内存空间。虚拟机执行JAVA程序的过程中会把它管理的内存划分为不同的数据区域方便管理。

11540

扫码关注云+社区

领取腾讯云代金券