五种OOM异常

如果你不相信努力和时光,那么成果就会是第一个选择辜负你的。不要去否定你自己的过去,也不要用你的过去牵扯你现在的努力和对未来的展望。不是因为拥有希望你才去努力,而是去努力了,你才有可能看到希望的光芒。五种OOM异常,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

heap Space OOM

这种异常经常出现,通常都会出现这个异常,表示内存空间不够,使用如下代码,用一个死循环来生产字符串,由于Java8之后字符串常量池放在堆里面,就会报这个异常

public static void main(String[] args) {
        String str = "aaaa";
        while (true){
            str += str + new Random().nextInt(); //Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        }
    }

GC overhead limit OOM

这种情况一般指GC线程运行的时间远大于用户线程的时间,比如说GC占了98%的CPU,用户线程只占了2%

设置如下JVM参数会生产这种异常:

  1. -Xmx10m
  2. -Xms10m
  3. -XX:+PrintGCDetails
  4. -XX:MaxDirectMemorySize=3m
public static void main(String[] args) {
        //Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
        //超过98%的时间来进行GC并且回收了不到2%的堆内存
        int i = 0;
        List<String> list = new ArrayList<>();
        while (true){
            list.add(String.valueOf(++i).intern());
        }
    }

Direct buffer memory OOM

一般在做nio异常的时候会出现

ps: ByteBuffer.allocate(capability) 第一种方式是分配JVM堆内存,属于GC管辖范围,由于需要拷贝所以速度相对较慢。 DirectByteBuffer dires = ByteBuffer.allocateDirect(capability),第二种方式是分配OS本地内存,不属于GC管辖范围,由于不需要内存拷贝所以速度相对较快。

DirectByteBuff 对象作为这块内存的引用进行操作,但如果不断分配本地内存,堆内存很少使用,那么JVM就不需要执行GC,DirectByteBuffer对象们就不会被回收,这时候堆内存充足,但本地内存已经使用光了,再次尝试分配本地内存就会出现OutOfMemoryError,那程序就直接崩溃了。

public static void main(String[] args) {
        System.out.println(VM.maxDirectMemory()+" MaxDirectMemory内存");
        //一般再做NIO异常的时候会出现
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
        //Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
 }

UnableToCreateNewNativeThread OOM

导致原因:

1. 你的应用创建了太多线程了,一个应用进程创建太多线程,超过系统承载极限
2. 你的服务器并不允许你的应用程序创建这么多线程,Linux系统默认会允许单个线程可以创建的线程数是1024个

验证代码:

 //到Linux主机上运行哈
    public static void main(String[] args) {

        for (int i = 0;; i++) {
            System.out.println("i= "+i);
            new Thread( () -> {
                System.out.println("i'm creating");
                try {
                    TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }

解决方案:

1. 修改服务器配置文件,增加每个线程的进程数
2. 想办法减低应用程序线程的数量

MetaSpace OOM

简单来说,就是元空间的内容太多,元空间的内存不足

设置参数: -XX:MetaSpaceSize=8m -XX:MaxMetaSpaceSize=8m

static class OOMTest{

    }

    public static void main(final String[] args) {
    
        int i = 0;//模拟计数多少次后发生异常

        try {
            while (true){
                i++;
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(OOMTest.class);
                enhancer.setUseCache(false);
                enhancer.setCallback(new MethodInterceptor() {
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        return methodProxy.invokeSuper(o,args);
                    }
                });
                enhancer.create();
            }
        }catch (Exception e){
            System.out.println("第多少次发生异常: "+i);
            e.printStackTrace();
        }

    }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/202485.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!