JVM深入JAVA虚拟机Jvm使用

[JVM]OOM实例分析

2017-02-06  本文已影响289人  伤口不该结疤

本文内容总结自《深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)》中的第2章。

Java内存区域
D:\>javac HeapOOM.java

D:\>java HeapOOM

D:\>java -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError HeapOOM
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid9512.hprof ...
Heap dump file created [27898328 bytes in 0.121 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 HeapOOM.main(HeapOOM.java:16)
使用IDE执行程序
 VM Args:
 -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError  
Option Description
-Xms20M -Xmx20M to specify that a maximum heap size of 20 Mbytes
-XX:+HeapDumpOnOutOfMemoryError Dump heap to file when java.lang.OutOfMemoryError is thrown
import java.util.ArrayList;
import java.util.List;

/**
 * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError  
 */
public class HeapOOM {
    static class OOMObject {

    }

    public static void main(String[] agrs) {
        List<OOMObject> list = new ArrayList<OOMObject>();

        while (true) {
            list.add(new OOMObject());
        }
    }
}
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid9512.hprof ...
Heap dump file created [15782234 bytes in 0.074 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2760)
    at java.util.Arrays.copyOf(Arrays.java:2734)
    at java.util.ArrayList.ensureCapacity(ArrayList.java:167)
    at java.util.ArrayList.add(ArrayList.java:351)
    at HeapOOM.main(HeapOOM.java:16)

使用MAT打开 java_pid9512.hprof,可以生成一个分析报告

使用MAT打开 java_pid9512.hprof

点击进入Dominator Tree界面,可以将对象占用Heap大小进行排序,由下图可以看出main thread里面生成了很多HeapOOM$OOMObject对象,导致暂用了97.49%的内存。

Dominator Tree
 VM Args:
 -Xss128k
/**
 * VM Args:-Xss128k
 */
public class JavaVMStackSOF {
    private int stackLength = 1;

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

    /**
     * @param args
     * @throws Throwable
     */
    public static void main(String[] args) throws Throwable {
        // TODO Auto-generated method stub
        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Throwable e) {
            // TODO: handle exception
            System.out.println("stack length : " + oom.stackLength);
            throw e;
        }
    }

}
stack length : 11432
Exception in thread "main" java.lang.StackOverflowError
    at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8)
    at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9)
    at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9)
    ... ...

运行时常量池是方法区的一部分,而方法区属于"永久代"(PermGen space)

  VM Args:
  -XX:PermSize=10M -XX:MaxPermSize=10M
import java.util.ArrayList;
import java.util.List;

/**
 * VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M
 */
public class RuntimeConstantPoolOOM {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        List<String> list = new ArrayList<String>();
        int i = 0;
        while (true) {
            list.add(String.valueOf(i++).intern());
        }
    }

}
JDK 1.6和JDK 1.7运行结果不同
 VM Args: 
-Xmx20M -XX:MaxDirectMemorySize=10M
import java.lang.reflect.Field;
import sun.misc.Unsafe;

/*
 * VM Args: -Xmx20M -XX:MaxDirectMemorySize=10M
 */
public class DirectMemoryOOM {
    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) throws IllegalArgumentException,
        IllegalAccessException {
        Field unsafeField = Unsafe.class.getDeclaredFields()[0];
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        while (true) {
            unsafe.allocateMemory(_1MB);
        }
    }
}
Exception in thread "main" java.lang.OutOfMemoryError
        at sun.misc.Unsafe.allocateMemory(Native Method)
        at DirectMemoryOOM.main(DirectMemoryOOM.java:16)
上一篇 下一篇

猜你喜欢

热点阅读