JVM线上故障排查的基本操作

前言

线上经常会遇到各种各样的问题,CPU 飚高,内存溢出,频繁 GC 。总的来说,基本上就是cpu、磁盘、内存以及网络等相关问题,所以进行排查时候尽量四个方面依次排查一遍。同时例如jstack、jmap等工具也是不囿于一个方面的问题的,基本上出问题就是df、free、top 三连,然后依次jstack、jmap伺候,具体问题具体分析即可。

示准JDK工县和实用程序

  • 基本工具 (appletviewer, extcheck, jar, java, javac, javadoc, javah, javap, jdb, jdeps)
  • 安全工具 (keytool,jarsigner, policytool, kinit, klist, ktab)
  • 国际化工具 (native2ascii)
  • 远程方法调用 (RMI) 工具 (rmic,rmiregistry,rmid,serialver)
  • Java IDL和RMI-IIOP工具 (tnameserv,idlj,orbd,servertool)
  • Java部署工具(avapackager,pack200,unpack200)
  • Java Web Start具 (javaws)
  • Java故障排除,性能分析,监视和管理工具 (jcmd,jconsole,jmc,jvisualvm)
  • Java Web服务工具 (schemagen,wsgen,wsimport,xjc)

实验性JDK工具和实用程序

  • 监视工具 (jps,jstat,jstatd)
  • 故障排除工具 (info,jhat,jmap,jsadebugd,jstack)
  • 脚本工具 (jrunscript)
    故障排除文档

本文的排查环境是 Linux

CPU 飚高

思路:首先找到 CPU 飚高的那个 Java 进程,因为你的服务器会有多个 JVM 进程。然后找到那个进程中的 “问题线程”,最后根据线程堆栈信息找到问题代码。最后对代码进行排查。

  1. 通过 top 命令找到 CPU 消耗最高的进程,并记住进程 PID
    在这里插入图片描述
  2. 再次通过 top -Hp [进程 PID] 找到 CPU 消耗最高的线程 ID,并记住线程 ID
    在这里插入图片描述
  3. 由于此时的线程 PID 是十进制的,而堆栈信息中的线程 PID 是 16 进制的,因此我们需要将 10 进制的转换成 16 进制的,并用这个线程 PID 在堆栈中查找,使用printf ‘%x\n’ pid,可以将 10 进制转换成 16 进制,得到nid
    在这里插入图片描述
  4. 通过 JDK 提供的 jstack 工具 jstack pid |grep ‘nid’ -C5 –color找到相应的堆栈信息,接着只要仔细分析一番即可。通常我们会比较关注WAITING和TIMED_WAITING的部分,BLOCKED就不用说了。我们可以使用命令cat jstack.log | grep “java.lang.Thread.State” | sort -nr | uniq -c来对jstack的状态有一个整体的把握,如果WAITING之类的特别多,那么多半是有问题
  5. 可以使用jstat -gc pid 1000命令来对gc分代变化情况进行观察
    。1000表示采样间隔(ms)
    。S0C/S1C、S0U/S1U、EC/EU、OC/OUMC/MU分别代表两个Survivor区、Eden区、老年代、元数据区的容量 和使用
    。YGC/YGT、FGC/FGCT、GCT则代表YoungGc、FullGc的耗时和次数以及总耗时

内存问题排查

内存问题排查起来就稍嫌麻烦,场景也比较多。主要包括OOM、GC问题和堆外内存。一般来讲,我们会先用free命令先来检查一发内存的各种情况。
在这里插入图片描述

堆内内存

内存问题大多还都是堆内内存问题。表象上主要分为OutOfMemory(OOM)StackOverflow(SOF)

OOM

JMV中的内存不足,OOM大致可以分为以下几种:

  • Exception in thread “main” java.lang.OutOfMemoryError: unable to create new native thread
    这个意思是没有足够的内存空间给线程分配java栈,基本上还是线程池代码写的有问题,比如说忘记shutdown,所以说应该首先从代码层面来寻找问题,使用jstack或者jmap。如果一切都正常,JVM方面可以通过指定Xss来减少单个thread stack的大小。另外也可以在系统层面,可以通过修改/etc/security/limits.confnofile和nproc来增大os对线程的限制

  • Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
    这个意思是堆的内存占用已经达到-Xmx设置的最大值,应该是最常见的OOM错误了。解决思路仍然是先应该在代码中找,怀疑存在内存泄漏,通过jstack和jmap去定位问题。如果说一切都正常,才需要通过调整Xmx的值来扩大内存。

  • Caused by: java.lang.OutOfMemoryError: Meta space
    这个意思是元数据区的内存占用已经达到XX:MaxMetaspaceSize设置的最大值,排查思路和上面的一致,参数方面可以通过XX:MaxPermSize来进行调整(这里就不说1.8以前的永久代了)。

SOF

栈内存溢出,这个大家见到也比较多。

  • Exception in thread “main” java.lang.StackOverflowError

表示线程栈需要的内存大于Xss值,同样也是先进行排查,参数方面通过Xss来调整,但调整的太大可能又会引起OOM。

使用JMAP定位代码内存泄漏

上述关于OOM和StackOverflow的代码排查方面,我们一般使用JMAP jmap -dump:format=b,file=filename pid来导出dump文件

另一方面,我们可以在启动参数中指定>-XX:+HeapDumpOnOutOfMemoryError来保存OOM时的dump文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值