StackOverFlow & OutOfMemory
StackOverFlow & OutOfMemory
两者都为 Error,广义上的“异常”
StackOverflow
通常为 Java 虚拟机栈内存不够,JVM 对方法栈只有入栈和出栈的操作,所以在此处要报异常,让方法一直加入到方法栈中,而不出栈,将栈爆满,即可报异常。
举个栗子(最简单的栗子,无限递归)
public class StackErrorTest {
    private static int count = 0;
    public static void main(String[] args) {
        System.out.println(count++);
        main(args);
    }
}

可以通过增加栈内存来解决部分问题,但不是长久解决方法,还是得优化代码。(-Xss1024m)(不建议设置太大,一般1M即可)栈大小设置


OOM
oom(java.lang.OutOfMemoryError)
Java heap space
和 StackOverflow 类似,JVM 堆空间不足,对象实例及数组几乎都放在堆空间中,所以可以一直加新的对象让堆空间爆满。
举个栗子
import java.util.ArrayList;
import java.util.List;
public class OOMTest {
    public static void main(String[] args) {
        List<O> list = new ArrayList<>();
        while (true){
            list.add(new O(1024*1024*1024));
            System.out.println(list.size());
        }
    }
}
class O{
    private byte[] bs;
    public O(int length){
        this.bs = new byte[length];
    }
}

同理,可以增加堆空间暂时解决问题 -Xms10240m -Xmx10240m
- -Xms 设置堆空间的初始内存大小 默认为内存 1/64
- -X 是jvm的运行参数
- ms memory start
- -Xmx 设置堆空间最大内存大小 默认为内存 1/4


MetaSpace(jdk8及以上)
属于元空间内存不够,元空间主要存放类信息,在加载过多的类会触发该报错,但在 jdk8 中方法区(8之后叫元空间)采用本地内存,最大值为本地运行内存大小,所以一般不会触发该报错。
修改元空间大小来触发报错
- -XX:MetaspaceSize=10m
- -XX:MaxMetaspaceSize=10m
设置初始大小为 10m,设置最大元空间大小为10m
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
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 o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    return methodProxy.invokeSuper(o,objects);
                }
            });
            enhancer.create();
        }
    }
    static class OOMObject{}
    
}

Direct buffer memory
本地直接内存不足,该内存不使用堆内存,不代表本地直接内存无限大,由于系统内存大小受限,所以本地内存和堆内存总和是有限制的,默认与堆内存大小一致
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
public class OOM2 {
    public static void main(String[] args) {
        int buffer = 1024 * 1024 * 100;	//100M
        List<ByteBuffer> list = new ArrayList<>();
        int count = 0;
        try {
            while (true){
                ByteBuffer direct = ByteBuffer.allocateDirect(buffer);
                list.add(direct);
                count++;
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println(count);
        }
    }
}


 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号