内存溢出

2019-12-24  本文已影响0人  紫色红色黑色

OutOfMemoryError

java.lang.OutOfMemoryError: Java heap space

原因:
1.在l号的heap中分配xxl号的内存;
2.内存泄露

下面代码演示堆内存溢出
-XX:+PrintGCDetails -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

public static void main(String[] args) {
    byte[] bytes = new byte[1 * 1024 * 1024];

    List<Object> list = new ArrayList<>();

    while (true) {
        list.add(bytes);
    }
}

Memory Leak

内存泄露的表现是内存溢出。下面是测试代码,向map中put元素,而元素没有重写equals()和hashCode(),所以map会判断key是新的,结果就是不停的向map中put元素。

public class MemLeadDemo {

    public final String key;

    public MemLeadDemo(String key) {
        this.key = key;
    }

    public static void main(String[] args) {
        try {
            Map map = System.getProperties();

            for (; ; ) {
                map.put(new MemLeadDemo("key"), "value");
                Thread.sleep(1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

jvm参数

-XX:+PrintGCDetails -Xmx10m -Xms10m -XX:+HeapDumpOnOutOfMemoryError

使用VisualVM(文档速度慢,需要等待)观察内存情况,需要安装插件Visual GC
。可以看到full gc越来越多,并且老生代并没有减少内存。

内存泄露

在内存溢出后查看dump文件,可以看到实例数最多的是散列表中的entry。


dump文件

java.lang.OutOfMemoryError: Metaspace

原因:加载类过多,超过Metaspace区域
下面代码演示metaspace溢出
-XX:+PrintGCDetails -XX:MaxMetaspaceSize=10m -XX:MetaspaceSize=10m -XX:+HeapDumpOnOutOfMemoryError

public static void main(String[] args) {
    while (true) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MetaOom.class);
        enhancer.setUseCache(false);
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                return proxy.invokeSuper(obj, args);
            }
        });


        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        enhancer.create();
    }
}

static class MetaOom {}

栈内存溢出

java.lang.StackOverflowError
-Xss160K设置每个线程栈内存

public static void main(String[] args) {
    StackOom oom = new StackOom();
    try {
        oom.recursive();
    } catch (Throwable throwable) {
        System.out.println(oom.count);
        throwable.printStackTrace();
    }
}

private int count = 0;
public void recursive() {
    count++;
    recursive();
}

引用

https://plumbr.io/outofmemoryerror
https://www.jianshu.com/p/2fdee831ed03
https://www.toptal.com/java/hunting-memory-leaks-in-java

上一篇下一篇

猜你喜欢

热点阅读