亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

上午系統崩潰,下午就喜提大禮包

標簽:
Java

前言

不好啦❗ 天塌了❗ 系统崩了❗

快看啊,程序outOfMemoryError了🙈

https://img1.sycdn.imooc.com/7cbfb26708f4f49e13920303.jpg


我的心里活动:“哈哈哈😀哈哈哈😀终于给我碰上了,这个问题可很少发生啊,又积累一个问题。虽然我昨天发了版本,但是作为公司技术最好,长得最帅的我,代码肯定不出现这个问题。”

不想看废话的直接看【解决过程和方案】 吧

排查过程

首先肯定是先看日志,根据日志信息可以看到三个关键信息:
1. 业务代码中调用了远程接口
2. 内存溢出outOfMemoryError
3. Arrays.copyOf(Arrays.java:3332)

猜想❔

得到关键信息后,看了代码之后我就和技术经理做了一个简单的讨论

  • 技术经理:调用远程接口没有设置超时时间,访问人数突然增多,导致请求阻塞。瞬间一万个请求进来,然后一个万的请求就阻塞了,从而导致内存溢出

  • 我的猜想:请求之前没有查询大量的数据,就算请求阻塞也不会占用大量内存,导致outOfMemory. 还有就是Tomcat的线程池也默认200,。就算一万个请求进来,同一时刻也最多处理200个请求,这个200个请求都阻塞的话会造成 系统卡死,但是不会出现outOfMemoryError

    虽然抛出了一个业务代码的错误,但是并不能肯定就是它引发的outOfMemoryError,也可能是其他任务占了太多内存,这个请求只是一根“稻草”

有趣的是,上午定位到问题,并确认是Android老哥写的,下午老哥就被约谈了,喜提大礼包。最近公司大裁员呀,已经裁了三分之一了,老哥们祝福我吧🧡🧡🧡

[需要看新机会的]
1、顺便吆喝一句,技术大厂,待遇给的还可以,就是偶尔有加班(放心,加班有加班费)
前、后端/测试,多地缺人,感兴趣的可以来试试~

解决过程和方案✔

1、修改启动命令,导出堆信息
定位outOfMemoryError 还得用证据说话呀! 让技术经理在启动命令上加了如下参数-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof 再次出现内存溢出就会将堆信息导出。

2、分析堆信息,定位大内存对象
因为之前已经装过分析dump文件的工具了,我用的是Intellij Profiler工具,打开堆快照文件如下:

https://img1.sycdn.imooc.com/671f9e6708f4f4bb18840252.jpg


根本问题已经浮出水面了,KbResultSetList<UnionCustomerCheckLog>这两个对象几乎把内存撑满了,jvm 堆内存最大1024M 这两个就占了700M. 算是定位到问题了吧! 也推翻了技术经理说的调用远程接口大量请求被阻塞的问题。

3、查找GC回收日志
我们搜索自己的业务包名字就行了,这样就能很快定位关键问题。发现存在service 名称 和 上面大对象的名称一致UnionCustomerCheckLog

https://img1.sycdn.imooc.com/f355176708f4f4c605460247.jpg


同样的搜索方式在summary栏目搜索,也能匹配上,并且定位到代码方法queryXXPassList()

https://img1.sycdn.imooc.com/5dd0376708f4f4d013030369.jpg


4、定位问题代码 、分析代码

找到关键代码之后我们就看看代码吧:

https://img1.sycdn.imooc.com/f51de96708f4f4db12100114.jpg


select * ? 这个写法是开发禁忌哦,加上这个sql 的查询的结果有40W 条了。

看看这个查询有啥用呢❓ 看看伪代码吧

下面代码就是用代码实现的分组统计........没错就是我们 Android 工程师写的,因为公司去年就不用维护客户端了,安卓写java,ios写前端。
刚好上午给老哥指出问题,下午就被人事约谈,领了大礼包了。

// 查询出需要的所属数据:40w条
List<UnionCustomerCheckLog> xxPassList = unionCustomerCheckLogService.queryXXPassList();

// 分组统计
Map<Integer, List<UnionCustomerCheckLog>> unionMap =
        xxPassList.stream().collect(Collectors.groupingBy(UnionCustomerCheckLog::getSource));
        
for (DictModel dict : modelList) {
    ChartVo vo = new ChartVo();
    vo.setName(dict.getText());
    List<UnionCustomerCheckLog> checkLogList = unionMap.get(Integer.valueOf(dict.getValue()));
    if (Objects.isNull(checkLogList)) {
        vo.setNumber(0L);
    } else {
        // 统计长度
        vo.setNumber((long) checkLogList.size());
    }
    voList.add(pieChartVo);
}

5、解决问题
既然上面已经分析出问题所在了,就是Android老哥还不太会分组统计,就把数据全部查询到内存中统计。导致outOfMemoryError.
解决方法修改统计,改成SQL分组统计就行了:

https://img1.sycdn.imooc.com/b7f2866708f4f4e908320124.jpg

程序逻辑也相应的调整就行了。

知识拓展

OutOfMemoryError 简单介绍

JVM 在内存不足时会先尝试 Full GC 回收无用对象。 如果 GC 后仍无法分配内存,才会抛出 OutOfMemoryError。 常见类型有:

  • 堆内存不足:java.lang.OutOfMemoryError: Java heap space

  • 元空间(方法区)不足:java.lang.OutOfMemoryError: Metaspace

  • 栈内存溢出:java.lang.StackOverflowError(本质是栈内存的 OOM)。

  • 直接内存不足:java.lang.OutOfMemoryError: Direct buffer memory

  • 垃圾回收(GC)超时:java.lang.OutOfMemoryError: GC overhead limit exceeded

    GC 时间占比过高:JVM 在连续多次 GC 中,超过 98% 的时间用于垃圾回收
    回收效果极差:每次 GC 后,堆内存释放量不足 2%
    持续触发:上述情况持续发生,导致 JVM 判定应用已无法通过 GC 恢复可用内存

OutOfMemoryError 系统会直接挂掉么?

不一定,主要看以下几个因素
1. 取决于 OOM 的类型和影响范围

  • 堆内存 OOM
    如果未捕获异常,仅当前线程终止,其他线程可能正常处理请求。 但堆内存不足可能导致后续请求继续触发 OOM,最终系统逐渐不可用。

  • 元空间 OOM(如类加载失败):可能导致 JVM 无法加载新类,影响功能完整性。
  • 栈溢出(StackOverflowError)通常仅终止当前线程,但如果是主线程崩溃,整个进程会退出。

2. JVM 配置的影响

  • -XX:+CrashOnOutOfMemoryError:强制 JVM 在 OOM 时立即崩溃,生成核心转储文件,系统不可用。

  • -XX:+HeapDumpOnOutOfMemoryError:仅生成堆转储文件,JVM 进程可能继续运行(但状态可能不稳定)。

3. 代码设计

  • 如果捕获了 OutOfMemoryError 并尝试释放资源(如关闭连接、清理缓存),可能恢复部分功能。

  • 但 OOM 通常是系统性问题的表现,即使捕获异常,应用状态可能已不可靠。

总结

由于工程师分组统计方式错误的实现,本来在数据库统计就行了,然而Android老哥却全部查询出来,然后再程序统计导致的内存溢出。

本篇文章分享了我去排查outOfMermoryError问题的过程,希望能帮到你,感谢一键三连!


——转载自作者:提前退休的java猿


點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
軟件工程師
手記
粉絲
3
獲贊與收藏
24

關注作者,訂閱最新文章

閱讀免費教程

  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消