登录
    Technology changes quickly but people's minds change slowly.

深入理解java虚拟机(三)–Java堆溢出

技术宅 破玉 1552次浏览 0个评论

java 堆溢出

我们将Java堆的大小为20M B,不可扩展(将堆的最小值-Xms参数与最大值-Xmx参数设置为一样即可避免堆自动扩展),并设置参数-XX:+HeapDumpOnOutOfMemoryError 转储快照文件

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

在idea 中可以如下配置

然后编写如下代码:

import java.util.ArrayList;
import java.util.List;

public class TestJvm {
    static class OOMObject {
    }
    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<OOMObject>();
        System.out.println("start");
        while (true) {
            list.add(new OOMObject());
        }
    }
}

运行后报如下异常:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid32473.hprof ...
Heap dump file created [28325168 bytes in 0.186 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Arrays.java:3210)
	at java.util.Arrays.copyOf(Arrays.java:3181)
	at java.util.ArrayList.grow(ArrayList.java:265)
	at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
	at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
	at java.util.ArrayList.add(ArrayList.java:462)
	at com.magicdu.cloud.magicmq.test.TestJvm.main(TestJvm.java:13)

然后我们打开Jprofiler,打开项目下转储的快照文件

就能看到内存占用最多的类了。然后再结合自己的程序分析溢出原因就可以了。
如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链,找到泄漏对象是通过怎样的引用路径、与哪些GC Roots相关联,才导致垃圾收集器无法回收它们,根据泄漏对象的类型信息以及它到GC Roots引用链的信息,一般可以比较准确定位到这些对象创建的位置,进而找出产生内存泄漏的代码的具体位置。
如果不是内存泄漏,换句话说就是内存中的对象确实都是必须存活的,那就应当检查Java虚拟机的堆参数(-Xmx与-Xms)设置,与机器的内存对比,看看是否还有向上调整的空间。再从代码上检查是否存在某些对象生命周期过长、持有状态时间过长、存储结构设计不合理等情况,尽量减少程序运行期的内存消耗。


华裳绕指柔, 版权所有丨如未注明 , 均为原创|转载请注明深入理解java虚拟机(三)–Java堆溢出
喜欢 (3)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址