最近排查了生产环境服务假死的问题,CPU 被占满,Java 中的线程都在执行 Full GC,为了 dump JVM 线程栈信息与堆内存信息,查了很多指令。下面做一个常用指令的简单汇总:

查看 Java 进程

jps

jrockit dump 操作

jrcmd <pid> hprofdump filename=/test.hprof

jstack dump 线程栈信息

jstack <pid> > test.dump
参数:
jstack [-l] <pid>: 连接到一个运行中的进程
jstack -F [-m] [-l] <pid>: 连接到一个挂起的进程
jstack [-m] [-l] <executable> <core>: 连接到核心文件
jstack [-m] [-l] [server_id@]<remote server IP or hostname>: 连接到远程调试服务

jmap dump 堆内存

jmap [option] <pid>: 连接到正在运行的进程
jmap [option] <executable <core>: 连接到核心文件
jmap [option] [server_id@]<remote server IP or hostname>: 连接到远程调试服务
option:
    无参数: 类似 Solaris pmap,查看虚拟机内存使用情况
        jmap 8888
    -heap: 打印 heap 的概要信息,GC 使用的算法,heap 的配置及 JVM 堆内存的使用情况
        jmap -heap 8888
    -histo[:live]: 打印 Java 堆对象的直方统计信息,live 参数加上只统计活的对象
        jmap -histo:live 8888
    -clstats: 打印类加载器的统计情况
        jmap -clstats 8888
    -finalizerinfo: 打印正等候回收的对象的信息
        jmap -clstats 8888
    -dump:<dump-options>: 使用 hprof 二进制形式,输出 jvm 的 heap 到文件,live 子选项可选只输出活的对象到文件
        jmap -dump:live,format=b,file=heap.bin 8888
    -F: 强制 dump,-dump 和 -histo 的 live 子参数无效
        jmap -heap -F 8888
    -J<flag>: 传递参数到 JVM 运行系统
        jmap -J-Xmx512m 8888

获取堆信息的 3 种方式

jmap -dump:live,format=b,file=heap.bin 8888

kill -3 <pid>

增加 JVM 启动参数
  -XX:+HeapDumpBeforeFullGC 
  -XX:HeapDumpPath=/dump

找到占用 CPU 过高的线程,分析

top
    定位到占用 CPU 高的进程 PID
top -H -p <pid> 或者 ps -mp <pid> -o THREAD,tid,time | sort -rn
    查看对应进程的哪个线程占用 CPU 过高
printf "%x\n" tid
    将需要的线程 ID 转换为 16 进制
jstack pid > pid.txt
jstack pid |grep tid -A 30
    导出 CPU 占用较高的进程的线程栈,用 16 进制 tid 在 pid.txt 查找;或打印线程的栈信息

jhat,分析 java 的堆,并启动一个 web server,可以将堆中对象的数量,大小等信息以 html 的形式显示出来,并支持对象查询语言。因占有大量内存,一般不在服务器上执行使用

jhat -J-Xmx512m <heap dump file>
http://ip:7000/,查看 html
执行对象查询语句 Object Query Language:select s from java.lang.String s where s.count > 100

jstat,查看堆内存各部分的使用量、垃圾回收、类编译、加载的情况

jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数]
    类加载统计:jstat -class 8888
        参数说明:
            Loaded:加载class的数量
            Bytes:所占用空间大小
            Unloaded:未加载数量
            Bytes:未加载占用空间
            Time:时间
编译统计:jstat -compiler 8888
    参数说明:
        Compiled:编译数量
        Failed:失败数量
        Invalid:不可用数量
        Time:时间
        FailedType:失败类型
        FailedMethod:失败的方法

垃圾回收统计:jstat -gc 8888
    参数说明:
        S0C:第一个幸存区的大小
        S1C:第二个幸存区的大小
        S0U:第一个幸存区的使用大小
        S1U:第二个幸存区的使用大小
        EC:伊甸园区的大小
        EU:伊甸园区的使用大小
        OC:老年代大小
        OU:老年代使用大小
        MC:方法区大小
        MU:方法区使用大小
        CCSC:压缩类空间大小
        CCSU:压缩类空间使用大小
        YGC:年轻代垃圾回收次数
        YGCT:年轻代垃圾回收消耗时间
        FGC:老年代垃圾回收次数
        FGCT:老年代垃圾回收消耗时间
        GCT:垃圾回收消耗总时间

堆内存统计:jstat -gccapacity 8888
    参数说明:
        NGCMN:新生代最小容量
        NGCMX:新生代最大容量
        NGC:当前新生代容量
        S0C:第一个幸存区大小
        S1C:第二个幸存区的大小
        EC:伊甸园区的大小
        OGCMN:老年代最小容量
        OGCMX:老年代最大容量
        OGC:当前老年代大小
        OC:当前老年代大小
        MCMN:最小元数据容量
        MCMX:最大元数据容量
        MC:当前元数据空间大小
        CCSMN:最小压缩类空间大小
        CCSMX:最大压缩类空间大小
        CCSC:当前压缩类空间大小
        YGC:年轻代gc次数
        FGC:老年代GC次数

新生代垃圾回收统计:jstat -gcnew 8888
    参数说明:
        S0C:第一个幸存区大小
        S1C:第二个幸存区的大小
        S0U:第一个幸存区的使用大小
        S1U:第二个幸存区的使用大小
        TT:对象在新生代存活的次数
        MTT:对象在新生代存活的最大次数
        DSS:期望的幸存区大小
        EC:伊甸园区的大小
        EU:伊甸园区的使用大小
        YGC:年轻代垃圾回收次数
        YGCT:年轻代垃圾回收消耗时间

新生代内存统计:jstat -gcnewcapacity 8888
    参数说明:
        NGCMN:新生代最小容量
        NGCMX:新生代最大容量
        NGC:当前新生代容量
        S0CMX:最大幸存1区大小
        S0C:当前幸存1区大小
        S1CMX:最大幸存2区大小
        S1C:当前幸存2区大小
        ECMX:最大伊甸园区大小
        EC:当前伊甸园区大小
        YGC:年轻代垃圾回收次数
        FGC:老年代回收次数


老年代垃圾回收统计:jstat -gcold 8888
    参数说明:
        MC:方法区大小
        MU:方法区使用大小
        CCSC:压缩类空间大小
        CCSU:压缩类空间使用大小
        OC:老年代大小
        OU:老年代使用大小
        YGC:年轻代垃圾回收次数
        FGC:老年代垃圾回收次数
        FGCT:老年代垃圾回收消耗时间
        GCT:垃圾回收消耗总时间

老年代内存统计:jstat -gcoldcapacity 8888
    参数说明:
        OGCMN:老年代最小容量
        OGCMX:老年代最大容量
        OGC:当前老年代大小
        OC:老年代大小
        YGC:年轻代垃圾回收次数
        FGC:老年代垃圾回收次数
        FGCT:老年代垃圾回收消耗时间
        GCT:垃圾回收消耗总时间


JDK1.7 永久代空间统计:jstat -gcpermcapacity 8888
    参数说明:
        PGCMN:最小永久代容量
        PGCMX:最大永久代容量
        PGC:当前新生成的永久代空间大小
        PC :永久代空间大小
        YGC:年轻代垃圾回收次数
        FGC:老年代垃圾回收次数
        FGCT:老年代垃圾回收消耗时间
        GCT:垃圾回收消耗总时间


JDK1.8 元数据空间统计:jstat -gcmetacapacity 8888
    参数说明:
        MCMN:最小元数据容量
        MCMX:最大元数据容量
        MC:当前元数据空间大小
        CCSMN:最小压缩类空间大小
        CCSMX:最大压缩类空间大小
        CCSC:当前压缩类空间大小
        YGC:年轻代垃圾回收次数
        FGC:老年代垃圾回收次数
        FGCT:老年代垃圾回收消耗时间
        GCT:垃圾回收消耗总时间


垃圾回收统计:jstat -gcutil 8888
    参数说明:
        S0:幸存1区当前使用比例
        S1:幸存2区当前使用比例
        E:伊甸园区使用比例
        O:老年代使用比例
        M:元数据区使用比例
        CCS:压缩使用比例
        YGC:年轻代垃圾回收次数
        FGC:老年代垃圾回收次数
        FGCT:老年代垃圾回收消耗时间
        GCT:垃圾回收消耗总时间


JVM编译方法统计:jstat -printcompilation 8888
    参数说明:
        Compiled:最近编译方法的数量
        Size:最近编译方法的字节码数量
        Type:最近编译方法的编译类型