前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何对jvm故障进行排查与定位?

如何对jvm故障进行排查与定位?

作者头像
用户1560186
发布2019-11-19 20:55:56
1.3K0
发布2019-11-19 20:55:56
举报
文章被收录于专栏:运维录运维录运维录

故障类型


线上的jvm故障基本可以分为两大类:

CPU____占用过高。

内存问题,通常可以理解为gc的问题,因为java的内存用gc进行管理。

故障排查兵器谱


命令行工具

jps等工具都是对tools.jar类的包装,使用起来方便简单.在下边的故障排查中会用到我们这里提到的工具,大家平时应该熟记于心.

  1. top: top命令用于实时显示 process 的动态。
  2. jps: JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程
jps
jps -l pid #输出主类的全名,如果进程执行的是jar包,输出jar包路径
jps -v pid #输出虚拟机进程启动时JVM参数
  1. jstat: JVM Statistics Monitoring Tool,用于收集HotSpot虚拟机各方面的运行数据
#我想监控gc,每250ms查询一次,一共查询20次,进程号为123
jstat -gc 123 250 20
  1. jinfo: Configuration Info for Java,显示虚拟机配置信息
  2. jmap: Memory Map for Java,生成虚拟机的内存转储快照(heap dump文件),jmap dump文件的时候会触发 FGC ,使用的时候注意场景)
 jmap pid
 jmap -histo:live pid > a.log  #当前Java进程创建的活跃对象数目和占用内存大小
 jmap -dump:live, format=b,file=xxx.xxx pid #当前Java进程的内存占用情况导出来
  1. jstack: Stack Trace for Java,显示虚拟机的线程快照

图形工具

1. jconsole: JVM各状态查看工具

  1. visualVM

CPU问题


CPU负载比较高的时候,我们需要先找到那个java进程,然后根据(进程ID)找到的那个”问题线程”,根据线程的堆栈信息找到代码,最后进行代码排查

1. top命令定位到cpu消耗最高的进程,并记住进程pid

通过 top -Hp pid 找到问题线程,记住线程 tid

2. 通过jstack -l tid >jstack.log 将线程堆栈信息dump到指定文件中

线程tid 是十进制的,堆栈中的线程id是16进制,使用 printf “%x\n” tid 转换。

3. 通过转化的16进制数字从堆栈信息中找到对应的线程堆栈.

如果有gc线程,可以推断内存泄露导致频发的gc,可以通过 jstat -gcutil pid 1s查看

[root@localhost ~]# jstat -gcutil 27534 1s
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
 0.00   0.00  100.00  99.34  91.25  82.89  52648  463.968   1439   3701.045  3473.868
  0.00  0.00   89.65  99.34  91.25  82.89  52649  463.975   1440   3711.702  3476.880
  0.00  0.00  100.00  99.34  91.25  82.89  52649  463.975   1440   3711.702  3476.880
  0.00  0.00  100.00   99.34  91.25  82.89  52649  463.975  1443   3714.241  3479.891
  0.00  0.00  100.00  99.34  91.25  82.89  52649  463.975   1443   3714.241 3479.891
  0.00  0.00  100.00  99.34  91.25  82.89  52649  463.975   1443   3714.241  3479.891
  0.00  0.00  100.00  99.34  91.25  82.89  52649  463.975   1444   3719.604  3483.889

可以看到每隔几秒就会full gc,而且Eden和Old都是99%,就是说每次full gc都没有回收到多少内存,所以一直在反复的跑

  1. jinfo用来查看运行中的虚拟机的参数,甚至在运行时动态修改一些JVM参数,选项-XX:+PrintFlagsFinal可以列出所有的JVM flag,而其中的标注为manageable的flag则是可通过JDK management interface(-XX:+PrintFlagsFinal)动态修改
[root@localhost ~]# java -XX:+PrintFlagsFinal -version | grep manageable
     intx CMSAbortablePrecleanWaitMillis            = 100                                 {manageable}
     intx CMSTriggerInterval                        = -1                                  {manageable}
     intx CMSWaitDuration                           = 2000                                {manageable}
     bool HeapDumpAfterFullGC                       = false                               {manageable}
     bool HeapDumpBeforeFullGC                      = false                               {manageable}
     bool HeapDumpOnOutOfMemoryError                = false                               {manageable}
    ccstr HeapDumpPath                              =                                     {manageable}
    uintx MaxHeapFreeRatio                          = 100                                 {manageable}
    uintx MinHeapFreeRatio                          = 0                                   {manageable}
     bool PrintClassHistogram                       = false                               {manageable}
     bool PrintClassHistogramAfterFullGC            = false                               {manageable}
     bool PrintClassHistogramBeforeFullGC           = false                               {manageable}
     bool PrintConcurrentLocks                      = false                               {manageable}
     bool PrintGC                                   = false                               {manageable}
     bool PrintGCDateStamps                         = false                               {manageable}
     bool PrintGCDetails                            = false                               {manageable}
     bool PrintGCID                                 = false                               {manageable}
     bool PrintGCTimeStamps                         = false                               {manageable}
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)

用jinfo打开以下选项,把full gc前后的虚拟机内存dump下来

jinfo -flag +PrintGC pid
jinfo -flag +PrintGCDetails pid
jinfo -flag HeapDumpPath=/home/rain/heapdump pid
jinfo -flag +HeapDumpBeforeFullGC pid
jinfo -flag +HeapDumpAfterFullGC pid

PrintGC和PrintGCDetails把gc日志输出到了nohup.out,查看nohup文件,可以看到full gc前后各dump了一次虚拟机内存,然后赶紧用jinfo关掉gc选项,选项前+号表示打开,-号表示关闭.

jinfo -flag -HeapDumpBeforeFullGC pid
jinfo -flag -HeapDumpAfterFullGC pid

在HeapDumpPath下找到dump下来的hprof文件,下载下来用Jprofile,jvisualvm 等工具都可以分析

内存问题


这里简单的说下,在java虚拟机中,内存分为: 新生代(Eden), 老年代(Old),永久代.

新生代存放朝生夕死的对象。

老年代存放从新生代迁移过来的周期较久的对象.

永久代是非堆内存的组成部分.主要存放加载类的class类级对象,比如说class本身,method,field等等。

在进行内存问题处理的时候,我们经常会碰到以下两种异常:

java.lang.OutOfMemoryError: PermGen space

如果出现这个异常,一般都是程序启动需要加载大量的第三方jar包,需要调整perm的内存设置

java.lang.OutOfMemoryError: Java heap space

如果出现这个异常,一般是由于虚拟机设置堆内存过小或者代码创建了大量的大对象,并且长时间不能被回收.

通常gc管理内存,一种是内存溢出,一种是内存没有溢出,gc处于亚健康情况

内存溢出的情况可以通过加上 -XX:+HeapDumpOnOutOfMemoryError 参数,该参数作用是:在程序内存溢出时输出 dump 文件

内存不溢出的情况比较复杂,一般gc会将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中的一块Survivor.当回收时,将Eden和Survivor中还存活着的对象一次性拷贝到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor的空间.HotSpot虚拟机默认Eden和Survivor的大小比例是8:1

YGC会经过两个过程,一个是扫描,一个是复制,扫描比较快,复制相对慢一些,如果每次都有大量的对象复制,STW(stop the world)时间会延长,另外一种情况是gc和系统的swap同时进行,也会延长STW时间

FGC触发原因有以下几个方面:

1.Old区内存不足

2.元数据区内存不足

3.cms promotion failed

4.concurrent mode failure.

5.jvm基于悲观策略认为ygc后old区无法放下晋升对象

6.jmap触发或者系统触发System.gc()

一般gc健康的情况下,YGC 5秒一次左右,每次不超过50毫秒,FGC 最好没有,CMS GC 一天一次左右gc超过5秒,说明系统内存过大,如果YGC频率过高,说明Eden区过小,可以增加Eden去。

内存问题的排查思路和cpu类似,在进行cpu分析的时候也顺带说了下内存:

通过top命令定位内存消耗最高的进程,并记住进程pid

jmap -histo:live pid查看当前进程创建的活跃对象的数目和占用内存的大小,从而定位代码。

对于一般的问题,通过这几个方面的思考,大致可以锁定问题所在,或是缩小问题可能发生的范围。例如对某些特定类型的内存泄漏来说,到这一步已经可以分析出是什么类型导致内存泄漏。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 故障类型
  • 故障排查兵器谱
  • CPU问题
  • 内存问题
相关产品与服务
命令行工具
腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档