一次真实的线上 OOM 问题定位

概述

       近日,负责的一系统生产环境上出现了OutOfMemoryError,伴随着这个问题随之而来的是一堆Full GC, CPU 百分之百,频繁宕机重启等问题,严重影响业务的推广及使用,此类问题一般处理起来比较棘手,本文将此问题的出现及定位解决过程做下梳理,以便对后续处理类似问题提供参考指导。       注:该问题前面发了一版,因有些描述不太恰当,后来删除了,少数先得者看到了,想再看下发现已被删除,私信咨询我怎么找不到了,由此可见,很多同事还是比较在意此类问题的,很好,重新梳理下,补上一篇。

问题出现

软件:WildFly standalone 8.1.0.Final(OpenJDK)
报警内容:日志中有OutOfMemoryError信息
环境:PRD
报警级别:严重
报警时间:2019-04-09 11:04:59
当前时间:2019-04-09 11:06:03
监控项名称:jboss日志OutOfMemoryError
最新数据:2019-04-09 11:03:38,791 ERROR [stderr] (RMI RenewClean-[net.sf.ehcache.distribution.ConfigurableRMIClientSocketFactory@1d4c0]) Exception in thread "RMI RenewClean-[net.sf.ehcache.distribution.ConfigurableRMIClientSocketFactory@1d4c0]" java.lang.OutOfMemoryError: Java heap space

第一步: 重启服务

做好机器隔离,重启服务,保证不影响业务使用!

第二步: 收集dump文件

第三步: 利用JVM故障处理工具分析问题

打开jvisualvm工具

载入dump文件

查找保留大小最大的对象

重点关注前几位

查看实例数最大的实例

分析可能的原因

从实例上看JDBC42ResultSet占用空间最大,从而大胆猜测与查询相关,那么就看详情中能否找到是哪个sql导致的问题, 查看owningstatemeng语句集:

查看原始sql: originalSql

sql详情:

纳尼,where 1=1?相当于没带条件查所有记录,那么,表中有多少记录呢,不多,也就20万不到吧

至此,改问题的原因似乎显而易见。

第四步:紧急发布

于当晚拉紧急版本,通宵发布处理,以免问题重现。

总结

此问题是由于研发人员疏漏,查询字典表数据未带查询条件,导致查出表中所有记录进行ORM处理导致内存溢出。定位过程看似简单,但如何能在第一时间迅速排查原因并给出解决方案,难度还是不小的,由于缺乏经验,往往不知该怎么入手,况且线上异常场景复杂多变,不保证这个地方优化了,后续就没有问题了,需要在 现网环境经住考验 才行。

事实证明,此问题优化后,现网仍然有较多其他问题待解决,目前正在组织专家会诊,待后续有时间再做总结吧。