美文网首页
OutOfMemory异常

OutOfMemory异常

作者: engineer_tang | 来源:发表于2021-11-06 10:13 被阅读0次

    1. JAVA堆溢出

    1.1 设置idea JVM参数

    image.png
    -Xmx30m -Xms20m -XX:+HeapDumpOnOutOfMemoryError
    

    1.2 代码示例

    代码如下:

    import java.util.ArrayList;
    import java.util.List;
    
    public class HeapOOM {
    
        static class OOMObject {}
    
        public static void main(String[] args) {
            List<OOMObject> list = new ArrayList<>();
            while(true) {
                list.add(new OOMObject());
            }
        }
    }
    
    image.png

    1.3 内存映像分析工具

    1. 在idea中搜索插件“JProfiler”,安装完成,并重启idea,当出现如下图图标,则表示安装成功。


      image.png

    2. 栈溢出

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

    配置Vm options参数:

    -Xss128k
    
    image.png

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

    3.1 运行时常量池溢出

    jdk7前,运行时常量池放在老年代,JDK7以后放在堆中。
    配置参数:

    -Xmx6m
    

    不提代码如下:

    import java.util.HashSet;
    import java.util.Set;
    
    public class RuntimeConstantPoolOOM {
    
        public static void main(String[] args) {
            Set<String> set = new HashSet<>();
            short i = 0;
            while(true) {
                set.add(String.valueOf(i++).intern());
            }
        }
    }
    
    image.png

    3.2 方法区内存溢出

    方法区是一个逻辑概念,其具体实现为jdk1.8的元空间与jdk1.8之前的永久代,他们之间最大的区别在于:元空间并不在JVM管理的内存中,而是使用本地内存。

    替代的原因
    1、1.8之前,字符串存在永久代中,容易出现性能问题和内存溢出,只有fullGC才会扫描清理到永久代,效率偏低。字符串常量
    2、类及方法的信息等比较难确定其大小,放入系统内存更为合适
    JVM options配置参数如下:

    -XX:MaxMetaspaceSize=20m
    

    示例代码如下

    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 obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        return methodProxy.invokeSuper(obj, args);
                    }
                });
                enhancer.create();
            }
        }
    
        static class OOMObject {}
    }
    
    image.png

    3.3 参数说明

    -XX:MaxMetaspaceSize: 设置元空间最大值,默认为-1,即不限制,或者说只受限于本地内存大小。
    -XX:MetaspaceSize: 指定元空间的初始空间大小,以字节为单位,达到该值就会触发垃圾收集进行类型卸载。
    -XX:MinMetaspaceFreeRatio: 作用是在垃圾收集之后控制最小的元空间剩余容量的百分比,可减少因为元空间不足导致的垃圾收集的频率。

    4. 本机直接内存溢出

    可通过 -XX:MaxDirectMemorySize参数指定,如果不指定则它和JAVA堆最大值一致。

    该区域内存溢出的明显特征是在Heap Dump文件中看不到明显异常,且Dump文件很小,程序中直接或间接使用了DirectMemory。

    相关文章

      网友评论

          本文标题:OutOfMemory异常

          本文链接:https://www.haomeiwen.com/subject/ekvhzltx.html