OutOfMemoryError

  • 配置VM arguments:
    -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
    可以显示内存状态等信息

堆溢出

  • 测试代码
public class testOom {
    static class OOMObject{};

    public static void main(String[] args) {
        List list = new ArrayList();
        while(true){
            list.add(new OOMObject());
        }
    }
}
  • 异常提示:
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
  • 解决方案
    • 通过内存映象分析工具(如EclipseMemory Analyzer)对Dump出来的堆转储快照进行分析,确认内存中的对象是否是必要的,也就是分析到底是出现内存泄漏还是内存溢出
    • 如果是内存泄漏,通过工具查看泄漏对象到GC Roots的引用链
    • 如果没有内存泄漏
      • 检查堆参数(-Xmx与-Xms)是否偏小;
      • 代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况

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

Java虚拟机规范描述了两种异常:

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

示例:无法跳出的递归

public class testOom2 {

    private int stackLength = -1;
    public void stackLeak(){
        stackLength++;
        stackLeak();
    }

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

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

书中示例使用String.intern(),不过JDK1.7以上版本用书中代码不会出错;
书中另一个示例用了CGLib直接操作字节码运行时生成大量动态类

本机直接内存溢出

-XX: MaxDirectMemorySize

你可能感兴趣的:(JVM)