多线程下的OOM问题

文章描述了一次服务器出现OOM问题的排查过程,从日志查看、代码分析、集群状态检查到问题定位,最终发现是服务器内存不足导致。通过测试代码展示了多线程中一个线程OOM时,虚拟机如何处理并回收资源,强调了监控内存使用和正确处理OutOfMemoryError的重要性。
摘要由CSDN通过智能技术生成

前言

最近的一台服务器出现了OOM的情况,出于好奇就进行了一些探查,这里做一些简单的记录

问题排查

日志查看

登陆服务器查看当天的报错日志,根据服务器的错误日志定位到了代码,发现是一个定时任务引起的,发现该定时任务报错的同时还有一个线程也在打印错误信息。所以想到了两个可能的问题:

  1. 新增的定时任务冲突,导致多个线程同时跑任务,导致最后OOM
  2. 源代码就有问题,数据量增多导致的定时任务出现的问题

代码查看

根据代码可以发现没有大对象的存在,最大的对象也只是几千万的Long对象,但是哪怕1亿的Long对象 也不会导致OOM,所以排出了代码问题。

集群查看

由于是分布式定时任务,也就是说定时任务是随机分发的,先对该任务的执行历史进行查看,发现执行的历史记录发现同一台机器,前一天失败了,但是后一天却成功了,而其他的所有机器都是成功的。也就是可以确定源代码应该没有问题。
在这里插入图片描述
所以怀疑是问题一导致的OOM,该服务器的JVM参数没同步,即可能数据量增多之后,其他的服务器都进行了扩容,但是该服务器忘记扩容导致的,故先去集群的监控中心查看其他的服务器的堆内存大小,发现确实该服务器的内存只有8G,而其他的服务器都已经扩容到了12G。再根据其他的禁用的服务器,发现都是8G。

问题解决

机器申请扩容最后成功解决问题

多线程OOM时候的回收

上面说在查看服务器的错误日志的时候,发现一个任务的所有线程都OOM了,但是另一个定时任务的线程没有立即结束,还在运行并进行日志的打印。故进行了简单测试,查看当多线程的情况下某个线程OOM之后会发生什么?怎么样才会彻底OOM直接宕机?

测试代码

public class OutOfMemoryTest {

    public static void main(String[] args) {
        new Thread(() -> {
            List<byte[]> list = new ArrayList<>();
            while (true) {
                list.add(new byte[1024 * 1024 * 50]);
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(1_000);
                } catch (Exception e) {
                }
            }
        }, "dead thread").start();

        new Thread(() -> {
            while (true) {
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(1_000);
                } catch (Exception e) {
                }
            }
        }, "alive thread").start();
    }
}

启动参数设置

-Xmx10m -Xms10m 设置堆大小为10m

控制台打印

根据控制台的打印可以发现在多线程的情况下,如果某个线程导致了OOM,虚拟机会终止该线程并回收它所占用的资源。但是,如果OOM是由于整个应用程序使用的内存超过了虚拟机的最大内存限制而导致的,那么整个虚拟机将会崩溃。

即当应用程序使用的内存超过了虚拟机的最大内存限制时,虚拟机会抛出OutOfMemoryError异常。如果该异常没有被捕获并处理,那么虚拟机将会崩溃,并且应用程序将无法继续执行。

因此,在编写多线程应用程序时,需要注意内存的使用情况,并且及时处理OutOfMemoryError异常,以避免整个虚拟机崩溃。
在这里插入图片描述
这个就好像是操作系统的资源分配一样,如果出现了资源的长时间持有,导致了可能死锁的发生,就允许剥夺该线程资源进行资源重分配。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值