实战 OutOfMemoryError异常

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/uotail/article/details/83386508

1、java堆溢出

代码如下

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

/**
 * Vm args:-Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError
 * 堆的最小值参数-Xms,堆的最大值参数-Xmx
 * -XX:+HeapDumpOnOutOfMemoryError表示让虚拟机在出现内存异常时Dump出当前的内存堆转储快照
 * -XX:HeapDumpPath:为快照文件位置
 * Java 堆内存溢出测试,深入理解java虚拟机 p51
 */
//-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:/
public class HeapOOM {

    static class OOMObject{}

    //psvm
    public static void main(String[] args) {

        List<OOMObject> list = new ArrayList<OOMObject>();
        while (true){
            list.add(new OOMObject());
        }
    }
}

运行

我们用Memory Analyzer 打开 dump出来的堆转储快照

官网:http://www.eclipse.org/mat/downloads.php 下载

打开

具体分析就不说了

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

/**
 * VM args:-Xss128k
 * -Xss128k 减小栈内存至128k
 */
public class JavaVMStackSOF  {

    private int stackLength=1;
    public void stackLeak(){
        stackLength++;
        stackLeak();
    }
    public static void main(String[] args) throws Throwable {
        JavaVMStackSOF oom=new JavaVMStackSOF();
        try{
            oom.stackLeak();;
        }catch (Throwable e) {
            System.out.println("stack length:" + oom.stackLength);
            throw e;
        }
 }
}

运行

 /**
 * VM args:-Xss2M
 * 该程序执行容易死机,我的电脑运行死机两次
 *
 */
public class JavaVMStatckOOM{
    public void dontStop(){
        while(true){    
        }
    }
    public void stackLeakByThread(){
        while(true){
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    dontStop();
                }
            });
            t.start();
        }
    }
    public static void main(String[] args) {
        JavaVMStatckOOM sofm = new JavaVMStatckOOM();
        sofm.stackLeakByThread();
    }
}

书上的运行结果如下

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


/**
 * VM args:-XX:PermSize=10M -XX:MaxPermSize=10M
 * PermSize 方法区大小
 */
public class RuntimeContantPoolOOM{
    public static void main(String[] args) {
        //使用List保存对常量池字符串的应用,避免Full GC回收常量池的行为
        List<String> list = new ArrayList<String>();
        //10M的PermSize在int的范围足够产生OutOfMemoryError
        int i = 0;
        while(true){
            list.add(String.valueOf(i++).intern());
        }
    }
}

运行结果(JDK1.6及之前的运行结果),
Exception in thread “main” java.lang.OutOfMemoryError: PermGen space
在jdk6及之前,常量池分配在永久代内,通过-XX:PermSize10M -XX:MaxPermSize=10M限制其大小,而JDK1.7后就不会出现相同的结果,while循环将一直进行下去。。。。。。

 public static void main(String[] args) {
        String str1 = new StringBuilder("计算机").append("软件").toString();
        System.out.println(str1.intern()==str1);
        String str2 = new StringBuilder("ja").append("va").toString();
        System.out.println(str2.intern() == str2);
        String str3 = new StringBuilder("goo").append("gle").toString();
        System.out.println(str3.intern() == str3);

    }

结果如下

/**
 * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
 */
public class JavaMethodAreaOOM {
 
    public static void main(String[] args) {
        while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OOMObject.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {
                    // TODO Auto-generated method stub
                    return proxy.invokeSuper(obj, arg);
                }
            });
            enhancer.create();
        }
    }
    static class OOMObject {
 
    }
}

 

运行结果:

Caused by: java.lang.OutOfMemoryError: PermGen space 

 

4、本机直接内存溢出


/**
 * VM Args:-Xmx20M -XX:MaxDirectMemorySize=10M
 */
public class DirectMemoryOOM {
    private static final int _1MB = 1024 * 1024;
    public static void main(String[] args) throws Exception {
        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 baby.oom.DirectMemoryOOM.main(DirectMemoryOOM.java:20) 

猜你喜欢

转载自blog.csdn.net/uotail/article/details/83386508