记录一次OOM查找原因的过程

11 篇文章 0 订阅

背景

在一次上班时,用户反馈系统卡了,后台监控发现内存溢出了,频繁地触发了FullGC,但是内存却一直没有降下来。
而由于每次遇上这种问题时都是急急忙忙,需要尽快恢复服务供用户使用,所以排查的机会也不多,这次记录下之前收藏的排查方法,便于后续使用。

操作步骤

概览(只是忘记步骤看此处即可)

  1. 执行jpsps命令 查看当前服务器中运行的java应用进程号
  2. jstack 进程号 > 指定文件名生成线程快照(相比于jmap对系统性能影响较小)
  3. top -Hp 进程号查看进程中的线程状态,记录/截图该进程中占用资源最多的前几个线程号
  4. printf "%x\n" 线程号命令将上一步获取到的线程号转为十六进制
  5. 在快照文件中根据十六进制线程号查找堆栈快照信息

详细步骤演示及说明

一、找到执行的java应用

  1. 执行jps或者ps命令,查看当前服务器中运行的java应用进程号
  • jps属于jdk的命令,简短地展示正在运行的java应用
    使用jps找到正在运行的java应用
  • ps属于Linux的命令,会展示详细的vm参数信息(如有多个java应用可根据应用路径找到自己的服务)
    使用ps命令显示正在运行的应用详情

二、生成线程堆栈快照

jstack 进程号 > 指定文件名

该命令对系统性能影响较小,不会像jmap造成系统STW(Stop The World)而无法运行,可以隔几秒或1分钟生成多几份

  • ./jstack 6166 > /data/appsvr/rookie/stack1.out
    jstack命令生成快照文件

三、查看进程中的线程状态,找到嫌疑线程

执行top -Hp 进程号查看进程中的线程状态,记录占用资源最多的前几个线程号,因为数据会动态变化,建议截几张图保存,用于后面转换十六进制在快照文件中查询
使用top命令记录下嫌疑线程

四、转换嫌疑线程为十六进制

printf "%x\n" 线程号命令将上一步获取到的线程号转为十六进制,用于在快照信息中进行查找,因为快照信息中记录的线程ID为十六进制
转换十六进制

五、在快照文件中查找调用栈信息

  1. Linux中使用less命令或者将文件拉下来根据转换的十六进制线程号查找栈信息
  2. 有时候占用CPU资源最多的线程号不一定是有用的信息,像我使用1820查找的内容就没有多少有效信息,反而使用19b7找到了执行的java代码
    1820线程的快照信息
    19b7的快照信息

反思

  • 当时出现问题时定位到了是数据导出的问题影响的,而对于文件导出逻辑,系统应该有导出日志供运维查看,而不必从后台查找,例如导出参数,报表名称,数据量,操作用户,开始时间等等
  • 还有一个目前未明白的是top命令监控的线程号和快照中实际运行的对应不上,看了程序没有启用多线程去处理导出,除了是生成快照时的处理线程跟监控时间差的问题外,还有其他原因导致吗?有大佬了解的话可以留下评论帮忙解答下
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值