一、JDK 工具

1. jps命令:查看所有的java进程

jps(JVM Process Status) 命令类似 UNIX 的 ps 命令。

  • jps: 显示虚拟机执行主类名称以及这些进程的本地虚拟机唯一 ID
  • jps显示 process information jps显示器显示没有运行_linux

  • jps -l:输出主类的全名,如果进程执行的是jar包,输出jar路径
  • jps显示 process information jps显示器显示没有运行_老年代_02

  • jps -v:输出虚拟机启动时的JVM参数
  • jps显示 process information jps显示器显示没有运行_linux_03

  • jps -m:输出传递给java进程的main函数的参数
  • jps显示 process information jps显示器显示没有运行_java_04

2. jstat:监视虚拟机各种运行状态信息

jstat(JVM Statistics Monitoring Tool) 使用于监视虚拟机各种运行状态信息的命令行工具。 它可以显示本地或者远程(需要远程主机提供 RMI 支持)虚拟机进程中的类信息、内存、垃圾收集、JIT 编译等运行数据,在没有 GUI,只提供了纯文本控制台环境的服务器上,它将是运行期间定位虚拟机性能问题的首选工具。

jstat 命令使用格式:

jstat - [-t] [-h] [ []]

常见的option如下:

  • jstat -class pid:显示 ClassLoader 的相关信息;
  • jstat -compiler pid:显示 JIT 编译的相关信息;
  • jstat -gc pid:显示与 GC 相关的堆信息;
  • jstat -gccapacity pid:显示各个代的容量及使用情况;
  • jstat -gcnew pid:显示新生代信息;
  • jstat -gcnewcapcacity pid:显示新生代大小与使用情况;
  • jstat -gcold pid :显示老年代和永久代的信息;
  • jstat -gcoldcapacity pid :显示老年代的大小;
  • jstat -gcpermcapacity pid:显示永久代大小;
  • jstat -gcutil pid:显示垃圾收集信息;

另外,加上 -t参数可以在输出信息上加一个 Timestamp 列,显示程序的运行时间。

例如:

  • jstat -gc -h3 31736 1000 10表示分析进程 id 为 31736 的 gc 情况,每隔 1000ms 打印一次记录,打印 10 次停止,每 3 行后打印指标头部

注释:S0C、S0U:Survivor 0区的大小及使用情况; S1C、S1U:Survivor 1区的大小及使用情况;EC、EU:Eden 区的大小及使用情况; OC、OU:old区的大小及使用情况;

MC、MU:Metaspace 区的大小及使用情况;CCS、CCSU:压缩类空间大小及压缩类空间使用大小;YGC、YGCT: YGC的次数和耗时;FGC、FGCT:FGC的次数和耗时;

GCT: GC的总时间=YGCT+FGCT

  • jstat -gccapacity -h3 16430 1000 10 标识分析进程ID为16430的内存中各代对象的使用情况和占用大小,每隔 1000ms 打印一次记录,打印 10 次停止,每 3 行后打印指标头部

jps显示 process information jps显示器显示没有运行_服务器_05

注释:NGCMN:新生代最小容量;NGCMX: 新生代最大容量;NGC:当前新生代容量;S0C:Survivor 0区的大小; S1C:Survivor 1区的大小; EC: eden区大小;OGCMN:老年代最小容量;

OGCMX:老年代最大容量;OGC:当前老年代容量; OC: 当前老年代容量;MCMN:最小元数据容量; MCMX:最大元数据容量;MC:当前元数据空间大小;CCSMN:最小压缩类空间大小;

CCSMX: 最大压缩类空间大小; CCSC: 当前压缩类空间大小;CCSC:当前压缩类空间大小;YGC:YGC次数;FGC:FGC次数

  • jstat -gcutil -h3 16430 1000 10 标识分析进程ID为16430 垃圾收集信息情况,每隔 1000ms 打印一次记录,打印 10 次停止,每 3 行后打印指标头部

注释:S0:幸存1区当前使用比例;S1:幸存2区当前使用比例;E:伊甸园区使用比例;O:老年代使用比例;M:元数据区使用比例;CCS:压缩使用比例;YGC:年轻代垃圾回收次数

FGC:老年代垃圾回收次数;FGCT:老年代垃圾回收消耗时间;GCT:垃圾回收消耗总时间

3. jinfo: 实时地查看和调整虚拟机各项参数(不重启虚拟机的情况下,可以动态的修改 jvm 的参数)

jinfo命令使用格式:

jinfo [option] pid : 输出当前 jvm 进程的全部参数和系统属性 (第一部分是系统的属性,第二部分是 JVM 的参数)

jinfo -flag [+|-]name pid : 开启或者关闭jvm对应名称的参数

jinfo -flag pid : 查看jvm对应参数的值

jinfo -flag = pid : 设置jvm对应的值到对应的参数

jinfo -flags pid :打印jvm相关参数

例如:

  • jinfo 28764 标识输出进程ID为28764的全部参数和系统属性

jps显示 process information jps显示器显示没有运行_JVM_06

  • jinfo -flag MaxHeapSize 28764 标识输出进程ID为28764的MaxHeapSize大小

jps显示 process information jps显示器显示没有运行_linux_07

  • jinfo -flag +PrintGC 28764 标识开启打印gc日志功能

4. jmap 生产堆存储快照

jmap命令使用格式:

jmap [option] pid

常见的option 如下:

  • jmap -heap pid 标识打印某个进程的堆的详细信息
  • jmap -dump:format=b,file=heap.bin pid 表示dump堆内存文件到heap.bin的文件中(format 格式,这里b是二进制的意思 ;file 保存路径及文件名;pid 进程号)
  • jmap -histo:live pid 查看堆中活动对象以及其大小
    例如:
  • jmap -heap pid
  • jmap -histo:live pid

jps显示 process information jps显示器显示没有运行_老年代_08

  • jmap -dump:format=b,file=heap.hprof 28764

5.jhat:分析heapdump文件

jhat 用于分析 heapdump 文件,它会建立一个 HTTP/HTML 服务器,让用户可以在浏览器上查看分析结果。打开localhost:7000便可以看见dump文件分析

jps显示 process information jps显示器显示没有运行_JVM_09

6.jstack :生成虚拟机当前时刻的线程快照

jstack命令主要用于调试java程序运行过程中的线程堆栈信息,可以用于检测死锁,进程耗用cpu过高报警问 题的排查。

jstack命令使用格式:

jstack [option]

options:

  • -F 强制dump线程堆栈信息. 用于进程hung住, jstack 命令没有响应的情况
  • -m 同时打印java和本地(native)线程栈信息,m是mixed mode的简写
  • -l 打印锁的额外信息

jstack使用姿势:

  1. top 查询出系统内最耗cpu的java进程。
  2. top -Hp 查询出进程中最耗时的线程ID
  3. printf “%x\n” <线程ID> 将第二步查询到的线程ID转换成16进制
  4. jstack -ml > 将jstack相关信息dump到文件上
  5. 通过https://fastthread.io/分析相关文件

jstack使用场景:

  • 线上系统cpu飙升

a.FGC次数过多

b.单纯cpu升高

1.系统cpu飙升,首先在机器上top查看系统cpu占用情况

jps显示 process information jps显示器显示没有运行_服务器_10


2. 可以看到,有一个Java程序此时CPU占用量达到了105.6%,此时我们可以复制该进程id 25904,并且使用如下命令查看呢该进程的各个线程运行情况:

top -Hp 25904

该进程下的各个线程运行情况如下:

jps显示 process information jps显示器显示没有运行_服务器_11

可以看出进程25904的线程25921消耗cpu 99.9%

  1. 通过以下命令把线程ID 25921转换成16进制为6541

printf “%x\n” 25921

  1. 通过下面命令,查询该线程相应堆栈信息

jstack 25904|grep 6541 -A 30

线程堆栈信息如下:

jps显示 process information jps显示器显示没有运行_linux_12


这里的VM Thread一行的最后显示nid=0x6541,这里nid的意思就是操作系统线程id的意思。而VM Thread指的就是垃圾回收的线程。这里我们基本上可以确定,当前系统缓慢的原因主要是垃圾回收过于频繁, 导致GC停顿时间较长。我们通过上面学习的jstat命令可以查看GC的情况:jstat -gcutil -h3 25904 1000 10

jps显示 process information jps显示器显示没有运行_linux_13


可以看到这里FGC的次数达到了4526686次,而且还在不停的增长。可以进一步证实是由于内存溢出导致的系统缓慢。

导致FGC的原因可能有

1.分配的堆内存比较小

2.代码中一次获取了大量的对象,导致内存溢出

通过jmap -heap 25409 查看该进程分配的堆内存大小,可以看出内存分配的不大

jps显示 process information jps显示器显示没有运行_JVM_14

通过命令 jstack 25409 > 25409.txt

  • 不定期出现的接口耗时现象
  • 某个线程进入WAITING状态
  • 死锁

jstack出的线程dump的各种状态:

二、Linux工具

1.top命令

top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器

jps显示 process information jps显示器显示没有运行_linux_15

参数含义:参考

top命令使用格式:

top [option]

参数说明:

  • -d 指定每两次屏幕信息刷新之间的时间间隔(默认是每隔5s显示所有进程的资源占用情况)。当然用户可以使用s交互命令来改变之。
  • -p 通过指定监控进程ID来仅仅监控某个进程的状态。
  • -q 该选项将使top没有任何延迟的进行刷新。如果调用程序有超级用户权限,那么top将以尽可能高的优先级运行。
  • -S 指定累计模式 s 使top命令在安全模式中运行。这将去除交互命令所带来的潜在危险。
  • -i 使top不显示任何闲置或者僵死进程。
  • -c 显示整个命令行而不只是显示命令名

例如:

  • top 表示每隔5s显示所有进程的资源占用情况
  • top -d 2 表示每隔2s显示所有进程的资源占用情况
  • top -c 表示每隔5s显示进程的资源占用情况,并显示进程的命令行参数(默认只有进程名)
  • top -p 12345 表示每隔5s显示pid是12345进程的资源占用情况
  • top -d 2 -c -p 123456 表示每隔2秒显示pid是12345的进程的资源使用情况,并显式该进程启动的命令行参数

三、可视化工具

1.jvisualvm — JVM监控

jvisualvm 是 jdk 提供的监控工具,位于 %JAVA_HOME%/bin/jvisualvm.exe,双击运行即可。

jvisualVM 提供了一个可视界面,用于查看JVM上运行的基于 Java 技术的应用程序的详细信息。VisualVM 能够监控线程,内存情况,方法的CPU时间和内存中的对象,已被GC的对象,反向查看分配的堆栈(如100个String对象分别由哪几个对象分配出来的)等。

更详细的一些使用方式可以参考这篇文章:zhuanlan.zhihu.com/p/30837957

a.插件安装

VisualVM 基于NetBeans平台开发工具,它具备通过插件扩展功能的能力,有了插件扩展支持,VisualVM可以做到:

  • 显示虚拟机进程以及进程的配置、环境信息(jps、jinfo)
  • 监视应用程序的处理器、垃圾收集、堆、方法区以及线程的信息(jstat、jstack)
  • dump 以及分析堆转储快照(jmap、jhat)
  • 方法级的程序运行性能分析,找出被调用最多、运行时间最长的方法
  • 离线程序快照:收集程序的运行时配置、线程dump、内存dump等信息建立一个快照,可以将快照发送开发者处进行Bug反馈
  • 其他插件带来的无限可能性

2.GCViewer — 离线分析GC日志

GCViewer 可以离线查看GC日志,下载地址为 github.com/chewiebug/G… 。下载下来之后执行 [mvn clean install -Dmaven.test.skip=true] 命令打包编译,编译完成后在target目录下会看到jar包,然后在命令行运行这个jar包就可以启动 GCViewer。然后通过 File 打开GC日志文件,就可以看到GC统计图和GC情况。通过工具,我们可以看到吞吐量、停顿时间以及 GC 的频率等信息,从而可以非常直观地了解到 GC 的性能情况

jps显示 process information jps显示器显示没有运行_服务器_16

3.GCeasy — 在线分析GC日志

GCeasy 是一款在线版的非常直观的 GC 日志分析工具,我们可以将日志文件压缩之后,上传到 GCeasy 官网即可看到非常清楚的 GC 日志分析结果。

GCeasy地址:https://gceasy.io/

jps显示 process information jps显示器显示没有运行_java_17

jps显示 process information jps显示器显示没有运行_服务器_18

4.FastThread — 分析线程栈

线程栈使用 jstack 命令 dump 下来后,可以使用 FastThread 在线工具分析线程栈信息,可以直观的看到有多少线程、线程池、线程的状态、是否有死锁等信息。

FastThread地址:https://fastthread.io/

jps显示 process information jps显示器显示没有运行_linux_19

5.Eclipse Memory Analyzer(MAT-分析堆存储文件)

我们使用 jmap 命令 dump 下来的堆转储文件可以使用 MAT 来分析,可以分析创建了哪些对象,然后分析对象的引用链,找出问题所在。

MAT 下载地址: http://www.eclipse.org/mat/downloads.php

MAT 主要功能:

  • 找出内存泄漏的原因
  • 找出重复引用的类和jar
  • 分析集合的使用
  • 分析类加载器

MAT具体使用可以参考这两篇文章:

MAT从入门到精通(一)

MAT从入门到精通(二)

6.附录

在线工具地址

线程 Dump 分析(FastThread): fastthread.io/

线程 Dump 分析(PerfMa): thread.console.perfma.com/

内存 Dump 分析(PerfMa): memory.console.perfma.com/

JVM 参数分析(PerfMa): opts.console.perfma.com/

GC 日志分析(GCEasy): www.gceasy.io/

GC 日志分析(GCViewer): github.com/chewiebug/G…

Java 诊断(Arthas): alibaba.github.io/arthas/

MAT: www.eclipse.org/mat/downloa…