java string 过长_java常见OutOfMemoryError总结!

    一般你去面试的时候,面试官经常会问:请谈谈你对OOM的认识?然后,你可能会说OOM就是out of memory,那如果你只是这么答的话,这可不是面试官想要的答案;面试官又接着问,那你生产过程中有遇到哪些OOM呢?请你说说出常见的OOM问题?这时的你可能是懵的。你知道几种常见的OOM呢?欢迎评论区留言。

常见的OOM总述:

220af86770e47974fcd33fc19518493c.png

1. StackOverflowError

    线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常 。递归调用方法,如果没有方法出口的方法会造成StackOverflowError,或者说如果调用的过深都会抛出,这种错误也比较容易定位。

public class StackOverflowErrorDemo {    public static void main(String[] args){        stackOverflowError();    }     private static void stackOverflowError() {        stackOverflowError();    }}

2. java.lang.OutOfMemoryError: Java heap space 

    溢出原因:深入理解Java虚拟机书中讲到java堆溢出,Java堆用于存储对象实例,只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量到达最大堆的容量限制后就会产生内存溢出异常。
import java.util.Random;public class JavaHeapSpaceDemo {    public static void main(String[] args){        String str = "seu";         while(true){            str += str + new Random().nextInt(11111111)+new Random().nextInt(22222222);            str.intern();        }    }}

568603f915687d39e4f40639503df336.png

3. java.lang.OutOfMemoryError:GC overhead limit exceeded

import java.util.ArrayList;import java.util.List;/** GC回收时间长时会抛出OutOfMemoryError。过长的定义是,超过98%的时间用来做GC并且回收了* 不到2%的堆内存,连续多次GC都只回收了不到2%的极端情况下才会抛出。假设不抛出GC overhead limit错误会发生什么情况呢?那就是GC清理的这么点内存很快会再次填满,迫使GC再次执行,这样就形成恶性循环,CPU使用率一直是100%,而GC缺没有任何成果。* */public class GCOverheadDemo {    public static void main(String[] args){        int i = 0;        List list = new ArrayList<>();        try{            while(true){                list.add(String.valueOf(++i).intern());            }        }catch (Throwable e){            System.out.println("***************i:"+i);            e.printStackTrace();            throw e;        }    }}

4. java.lang.OutOfMemoryError:Direct buffer memory

import java.nio.ByteBuffer; /** * 配置参数:-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m * 导致原因: *  写NIO程序经常使用ByteBuffer来读取或者写入数据,这是一种基于通道,缓冲区的IO方式 *   ByteBuffer.alloction(capabicity)分配jvm堆内存,属于GC管辖范围 *   ByteBuffer.allocateDirect(capabicity)分配本地内存,不属于GC管辖范围,由于不需要内存拷贝所以速度较快。 *   如果不断分配本地内存,但是堆内存很少使用,那么jvm不需要执行GC,DirectByteBuffer对象就不会被回收,这时候堆内存充足 *   但是本地内存已经使用光了,再次分配的时候就会出现OOM异常! *   --堆内存不够的时候,会触发fullGC顺带回收 DirectMemory! *   MaxDirectMemorySize 默认是64M */public class DirectBufferMemoryDemo {    public static void main(String[] args) {        System.out.println("配置的MaxDirectMemory:"+(sun.misc.VM.maxDirectMemory()/(double)1024/1024)+"MB");        try{Thread.sleep(3000);} catch (InterruptedException e) { e.printStackTrace();}         //-XX:MaxDirectMemorySize=5m 我们配置为5M 但是实际使用是6M        ByteBuffer.allocateDirect(6*1024*1024);    }}

5. java.lang.OutOfMemoryError:unable to create new native thread

   不知道你们生产环境是否会出现这种情况,高并发请求服务器时,经常出现如下异常java.lang.OutOfMemoryError:unable to create new native thread。那出现的原因呢?

    1.创建太多的线程了

    2.服务器的设置限制了你创建线程的数量了(linux 允许创建的线程数是1024个)

6. java.langOutOfMemoryError:Metaspace

   我们知道Java8及以后已经使用Metaspace来替代永久代,Metaspace并不在虚拟机内存中而是使用本地内存。主要还是是加载到内存中的 class 数量太多或者体积太大。这时可以通过JVM参数-XX:MaxMetaspaceSize指定。
* JVM参数:-XX:MetaspaceSize=8m  -XX:MaxMetaspaceSize=8m * Java8之后的版本使用Metaspace来替代永久代 * Metaspace是方法区在HotSpot中的实现,它与持久带最大的区别在于:Metaspace并不在虚拟机内存中而是使用 * 本地内存,也即在java8中,class metaspace(the virtual machines internal presentation of java class) * ,被存储在叫做Metaspace的native memory * * 永久代(Metaspace)存放以下信息: * 虚拟机加载的类信息 * 常量池 * 静态变量 * 即时编译后的代码 * */public class MetaspaceOOMT {    static class OOMTest {    }     public static void main(String[] args) {        int i = 0;//模拟多少次后发生异常        try {            while (true) {                i++;                Enhancer enhancer = new Enhancer();                enhancer.setSuperclass(OOMTest.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, args);                    }                });                enhancer.create();            }        } catch (Throwable e) {            System.out.println("********多少次后发生了异常:" + i);            e.printStackTrace();        }    }}

总结:

   理解jvm才能更有深度的理解这些异常,对jvm的学习应该贯穿整个java!欢迎大家转载,分享,关注我的公众号,一起学习!

如公众号不方便查看,欢迎关注我的博客:https://blog.csdn.net/zhangkaixuan456/article/details/108083096

                      ec63609a951048dda8b0ee04199c3ab2.png

         关注「Java源码进阶」,获取海量java,大数据,机器学习资料!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值