首页 > 其他分享 >工作中最常见的6种OOM问题

工作中最常见的6种OOM问题

时间:2024-03-18 09:34:20浏览次数:21  
标签:lang java OOM 常见 工作 GC 内存 public

前言

最近我写的几篇线上问题相关的文章:《糟糕,CPU100%了》《如何防止被恶意刷接口》《我调用第三方接口遇到的13大坑》发表之后,在全网广受好评。

今天接着线上问题这个话题,跟大家一起聊聊线上服务出现OOM问题的6种场景,希望对你会有所帮助。

1 堆内存OOM

堆内存OOM是最常见的OOM了。

出现堆内存OOM问题的异常信息如下:

java.lang.OutOfMemoryError: Java heap space

此OOM是由于JVM中heap的最大值,已经不能满足需求了。

举个例子:

public class HeapOOMTest {

    public static void main(String[] args) {
        List<HeapOOMTest> list = Lists.newArrayList();
        while (true) {
            list.add(new HeapOOMTest());
        }
    }
}

这里创建了一个list集合,在一个死循环中不停往里面添加对象。

执行结果:

出现了java.lang.OutOfMemoryError: Java heap space的堆内存溢出。

很多时候,excel一次导出大量的数据,获取在程序中一次性查询的数据太多,都可能会出现这种OOM问题。

我们在日常工作中一定要避免这种情况。

2 栈内存OOM

有时候,我们的业务系统创建了太多的线程,可能会导致栈内存OOM。

出现堆内存OOM问题的异常信息如下:

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

给大家举个例子:

public class StackOOMTest {
    public static void main(String[] args) {
        while (true) {
            new Thread().start();
        }
    }
}

使用一个死循环不停创建线程,导致系统产生了大量的线程。

执行结果:

如果实际工作中,出现这个问题,一般是由于创建的线程太多,或者设置的单个线程占用内存空间太大导致的。

建议在日常工作中,多用线程池,少自己创建线程,防止出现这个OOM。

3 栈内存溢出

我们在业务代码中可能会经常写一些递归调用,如果递归的深度超过了JVM允许的最大深度,可能会出现栈内存溢出问题。

出现栈内存溢出问题的异常信息如下:

java.lang.StackOverflowError

例如:

public class StackFlowTest {
    public static void main(String[] args) {
        doSamething();
    }

    private static void doSamething() {
        doSamething();
    }
}

执行结果:

出现了java.lang.StackOverflowError栈溢出的错误。

我们在写递归代码时,一定要考虑递归深度。即使是使用parentId一层层往上找的逻辑,也最好加一个参数控制递归深度。防止因为数据问题导致无限递归的情况,比如:id和parentId的值相等。

4 直接内存OOM

直接内存不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。

它来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存,是属于堆外内存,可以直接向系统申请的内存空间。

出现直接内存OOM问题时异常信息如下:

java.lang.OutOfMemoryError: Direct buffer memory

例如下面这样的:

public class DirectOOMTest {

    private static final int BUFFER = 1024 * 1024 * 20;

    public static void main(String[] args) {
        ArrayList<ByteBuffer> list = new ArrayList<>();
        int count = 0;
        try {
            while (true) {
                // 使用直接内存
                ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
                list.add(byteBuffer);
                count++;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } finally {
            System.out.println(count);
        }
    }
}

执行结果:

会看到报出来java.lang.OutOfMemoryError: Direct buffer memory直接内存空间不足的异常。

5 GC OOM

GC OOM是由于JVM在GC时,对象过多,导致内存溢出,建议调整GC的策略。

出现GC OOM问题时异常信息如下:

java.lang.OutOfMemoryError: GC overhead limit exceeded

为了方便测试,我先将idea中的最大和最小堆大小都设置成10M:

-Xmx10m -Xms10m

例如下面这个例子:

public class GCOverheadOOM {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            executor.execute(() -> {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                }
            });
        }
    }
}

执行结果:

出现这个问题是由于JVM在GC的时候,对象太多,就会报这个错误。

我们需要改变GC的策略。

在老代80%时就是开始GC,并且将-XX:SurvivorRatio(-XX:SurvivorRatio=8)和-XX:NewRatio(-XX:NewRatio=4)设置的更合理。

最近就业形式比较困难,为了感谢各位小伙伴对苏三一直以来的支持,我特地创建了一些工作内推群, 看看能不能帮助到大家。

你可以在群里发布招聘信息,也可以内推工作,也可以在群里投递简历找工作,也可以在群里交流面试或者工作的话题。

进群方式

添加苏三的私人微信:su_san_java,备注:博客园+所在城市,即可加入。

6 元空间OOM

JDK8之后使用Metaspace来代替永久代,Metaspace是方法区在HotSpot中的实现。

Metaspace不在虚拟机内存中,而是使用本地内存也就是在JDK8中的ClassMetadata,被存储在叫做Metaspace的native memory。

出现元空间OOM问题时异常信息如下:

java.lang.OutOfMemoryError: Metaspace

为了方便测试,我修改一下idea中的JVM参数,增加下面的配置:

-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m

指定了元空间和最大元空间都是10M。

接下来,看看下面这个例子:

public class MetaspaceOOMTest {
    static class OOM {
    }

    public static void main(String[] args) {
        int i = 0;
        try {
            while (true) {
                i++;
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(OOM.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) {
            e.printStackTrace();
        }
    }
}

执行结果:

程序最后会报java.lang.OutOfMemoryError: Metaspace的元空间OOM。

这个问题一般是由于加载到内存中的类太多,或者类的体积太大导致的。

好了,今天的内容先分享到这里,下一篇文章重点给大家讲讲,如何用工具定位OOM问题,敬请期待。

最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙扫描下发二维码关注一下,您的支持是我坚持写作最大的动力。
求一键三连:点赞、转发、在看。
关注公众号:【苏三说技术】,在公众号中回复:面试、代码神器、开发手册、时间管理有超赞的粉丝福利,另外回复:加群,可以跟很多BAT大厂的前辈交流和学习。

标签:lang,java,OOM,常见,工作,GC,内存,public
From: https://www.cnblogs.com/12lisu/p/18079649

相关文章

  • 一线/顶级的机器人公司(双足、四足、人形机器人)都在忙啥/主要工作是啥?
    参考:https://www.youtube.com/watch?v=NOljjZP75Gg很多AI方向的人认为这些世界顶级的机器人公司一定是把大量的时间和精力放在了AI技术研发上了,其实不然,AI技术在实体产业上的使用其实并没有想象中的那么大的距离,甚至可以把这个理解为work就OK,尤其机器人公司其实并不需要想那......
  • 说一说监控中常见的电视墙管控功能
    一、说说电视墙是怎么构成的电视墙主要有两种构成方式第一种:整体一块屏,尤其是是小间距的Mini/MicroLED技术构成的完整一块屏这样的,类似下面图:  这个整体一个屏的造价目前也不是很贵,中档的大概1平方米一万左右。这种屏重要的参数就是点间距,点指的就是LED的基本组成部分模......
  • CSS常见选择器
    1.基础选择器   选择器作用:查找标签设置样式标签选择器:使用标签名作为选择器类选择器:(1)定义类选择器-->.类名(2)使用类选择器标签添加class="类名"<style>/*定义*/.green{color:green;}.size{font-size:10px;}<......
  • 常见排序算法(C/C++)--- 动画演示
        本篇将介绍一些常见的排序算法,如插入排序:直接插入排序、希尔排序;选择排序:选择排序、堆排序;交换排序:快速排序、冒泡排序;以及最后的归并排序。    对于以上的排序算法,我们总结了每种排序算法的特性,接着对直接插入排序进行了优化;然后实现了归并排序和快速排......
  • HTML学习笔记1: 常见标签
    HTML常见标签p段落标签<p>段落内容</p>b加粗标签<b>加粗标签</b>strong加粗+强调标签strong和b在样式上没有什么差别,只是便于强调区分<strong>强调+加粗标签</strong>img图片标签src图片路径(绝对磁盘路径,绝对网页路径,相......
  • 2023性能测试工作积累
    一 理论1、性能调优思路:性能瓶颈点分析、关键参数调整、sql调优。调优过程中,通过系统资源、吞吐量、负载等因素来辅助分析。性能调优流程: 确定调优范围:服务器CPU、内存、IO、网络是否已被充分利用,是否存在瓶颈点。 系统调优:目的是充分利用服务器资源,避免资源冲突,提升吞吐量......
  • 视频监控中常见的桌面轮询是什么意思?
    什么叫桌面轮询?常见的视频监控系统可能管理着几十路甚至上千路甚至上万路视频。从预览画面的角度,就会出现既可以手工点播的需求(也就是想看谁就去找到这个摄像机,然后点击播放,这是最常见的一个功能),也会出现来回滚动很多路播放视频,一次播放9个画面这样的需求,这个就是轮询功能。......
  • Java 8中 lambda表达式、Stream API的常见用法
    1、取出集合中的某个字段://拿到车辆idsList<Long>carIds=parkCarInDbList.stream().map(ParkCar::getId).collect(Collectors.toList());2、集合直接进行遍历然后进行相关操作:List<Car>cars=carService.getListByCarId(carIds);cars.forEach(car->......
  • 【每日算法】常见AIGC模型; 刷题:力扣单调栈
    上期文章【每日算法】理论:生成模型基础;刷题:力扣单调栈文章目录上期文章一、上期问题二、理论问题1、stablediffusion模型的网络架构2、T5的网络架构(Text-To-TextTransferTransformer模型)3、SDXL模型4、DALLE5、BPE编码6、为什么DDPM加噪声的幅度是不一致的?三、力......
  • python--模块导入+路径处理+常见异常类型
    python--模块导入+路径处理+常见异常类型模块导入import模块名from模块名import类、变量、函数from模块名import*from项目名.包.py文件名称import类、变量、函数导包快捷键os模块路径处理路径获取os.path.dirname(__file__)os.path.abspath('test.txt')os.g......