zoukankan      html  css  js  c++  java
  • Jvm FullGC 如何排查?

    使用场景

    我们在使用系统时,有时请求和响应会变得特别慢,系统也变得很卡。

    有可能是FullGC的问题,可以逐步地进行排查。

    使用jps和top确定进程号pid

    jps可以列出正在运行的jvm进程,并显示jvm执行主类名称( main()函数所在的类),以及进程id。

    命令如下:

    jps -l
    

    结果如下:

    而top命令查看cpu使用情况,获取对应的进程号pid:

    top
    

    如下所示,发现进程号pid为72的进程占用了近100%的cpu:

    jstat检查进程号的gc,是否发生fullGC:

    jstat,就是JVM Statistics Monitoring Tool.
    下面这个命令的意思是每隔2s显示pid为72的进程的GC情况:

    jstat -gcutil 72 2000
    

    结果如下:

    我们主要观察FGC这个参数,可以发现,每隔几秒,FGC的次数就会变多。

    具体的含义如下:

    参数含义:
    S0 : Heap 上的 Survivor space 0 段已使用空间的百分比
    S1 : Heap 上的 Survivor space 1 段已使用空间的百分比
    E : Heap 上的 Eden space 段已使用空间的百分比
    O : Heap 上的 Old space 段已使用空间的百分比
    P : Perm space 已使用空间的百分比
    YGC :从程序启动到采样时发生 Young GC 的次数
    YGCT : Young GC 所用的时间 ( 单位秒 )
    FGC :从程序启动到采样时发生 Full GC 的次数
    FGCT : Full GC 所用的时间 ( 单位秒 )
    GCT :用于垃圾回收的总时间 ( 单位秒 ) 
    

    查看在这个进程中消耗cpu最多的线程

    命令如下:

    top -H -p 72
    

    可以查看在72这个进程的各个线程
    -H表示 Threads-mode operation,线程模式,展示各个线程。
    -p表示 Monitor-PIDs mode,监控模式,通过进程id监控进程。
    详情见: https://blog.csdn.net/qq_31302009/article/details/77803006

    结果如下,可以看到消耗cpu最多的线程号80和79:

    • 计算线程号的16进制结果
    printf %x 79
    

    将线程号80和79分别转换成16进制,将结果4f和50记下来,可以在后面的dump文件搜索。

    jstack分析线程堆栈,并保存结果

    • 根据进程号,输出进程的线程dump文件。

    以下命令是将进程号为72的dump文件,输出到 /tmp/dump_file这个路径,也可以是其他任意路径。

    > 表示将命令执行的结果保存到文件并覆盖原文件的内容。

    jstack 72 > /tmp/dump_file
    
    • 打开dump文件,根据之前printf %x计算得到的16进制结果搜索。

    比如printf %x 79 计算得到的结果为4f,可以通过4f进行搜索,也可以用0x4f搜索。

    (注:如果不想保存文件,也可以直接用命令

    jstack -l 72 | grep 0x4f -C 10 
    

    jstack -l显示线程堆栈详情,grep匹配关键字0x4f,-C 10表示显示关键字前后10行。)

    主要看nid。 nid,意思是 native thread id. 每一个nid对应于linux下的一个tid。
    jstack中的nid是十六进制数。
    搜索找到 nid=0x4f 的线程,就可以拿到线程的堆栈,找到出问题的代码了。

    jmap分析进程的内存使用情况

    • jmap分析进程72的内存使用情况,并保存dump文件

    jmap,就是Java Memory Map.

    jmap -histo 72 > pid72.log
    

    以上命令中的 pid72.log是文件名称,也可以改用其他名称。而72是进程号。

    查到 pid72.log 文件,内存的使用情况如下:

    参数的含义如下:

    说明:
    
    #instance 是对象的实例个数
    #bytes 是总占用的字节数
    class name 对应的就是 Class 文件里的 class 的标识
    B 代表 byte
    C 代表 char
    D 代表 double
    F 代表 float
    I 代表 int
    J 代表 long
    Z 代表 boolean
    前边有 [ 代表数组, [I 就相当于 int[]
    对象用 [L+ 类名表示 
    

    jhat分析jmap生成的堆内存快照

    jhat,就是JVM Heap Analysis Tool,虚拟机堆内存快照分析工具。
    jhat,可以用来分析jmap生成的堆内存文件。
    除了jhat,也可以用专业用于分析dump文件的Memory Analyzer(MAT)等工具。

    jmap -dump:format=b,file=a.hprof 72
    jhat -J-Xmx512M a.hprof
    

    a.hprof是文件名称,也可以改用其他命名。

    结果如下:

    屏幕显示"Server is ready."的提示后,用户在浏览器中输入http://要访问的ip:7000/,
    比如 http://localhost:7000/ 就可以看到分析结果了。

    分析结果默认是以包为单位进行分组显示,分析内存泄漏问题主要会使用到其中的 "Heap Histogram",可以找到内存中总量最大的对象。

    参考资料

    《深入理解java虚拟机》
    https://blog.csdn.net/weixin_34320159/article/details/91553350
    https://www.cnblogs.com/kongzhongqijing/articles/3621223.html
    https://www.cnblogs.com/kingszelda/p/9034191.html

  • 相关阅读:
    4-1 软件原型设计
    3-1 案例分析
    2-1 编程作业
    1-2阅读任务
    1-1 准备工作
    第十周学习总结
    实验报告2&&第四周课程总结
    Java实验报告(一)&&第三周学习总结
    第三周编程总结
    2019年春季学期第二周作业
  • 原文地址:https://www.cnblogs.com/expiator/p/14530928.html
Copyright © 2011-2022 走看看