JVM监控及诊断工具(命令行)

概述

性能诊断是软件工程师日常工作中需要经常面对和解决的问题,在用户体验至上的今天,解决好应用的性能问题能带来非常大的收益。

Java作为最流行的编程语言之一,其应用性能诊断一直受到业界广泛关注。可能造成Java应用出现性能问题的因素非常多,例如线程控制、硬盘读写、数据库访问、网络I/O、垃圾收集等。想要定位这些问题,一款优秀的性能诊断工具必不可少。

简单的命令行工具

在我们刚接触java学习的时候,大家肯定最先了解的两个命令就是javac、java,那么除此之外,还有没有其他的命令可以供我们使用呢?我们进入到安装jdk的bin目录,发现还有一系列的辅助工具。这些辅助工具用来获取目标JVM不同方面、不同层次的信息,帮助开发人员很好地解决Java应用程序的一些疑难杂症。

jps 查看正在运行的Java进程

基本情况

jps(Java Process Status):显示指定系统内所有的HotSpot虚拟机进程(查看虚拟机进程信息),用来查询正在运行的虚拟机进程。
说明:对于本地虚拟机进程来说,进程的本地虚拟机ID与操作系统的进程ID是一致的,是唯一的。

基本用法

jsp

  1. options参数
    -q: 仅仅显示LVMID( local virtual machine id),即本地虚拟机唯一id。不显示主类的名称等。
    -l: 输出应用程序主类的全类名 或 如果进程执行的是jar包,则输出jar包完整路径
    -m: 输出虚拟机进程启动时传递给主类main()的参数
    -v: 列出虚拟机进程启动时的JVM参数。比如:-Xms20m -Xmx50m是启动程序指定的jvm参数

    补充:如果某Java进程关闭了默认开启的UsePerfData参数(即使用参数-XX:-UsePerfData),那么jps命令(以及下面介绍的jstat)将无法探知该Java进程。

  2. hostid参数
    RMI注册表中注册的主机名。
    如果想要远程监控主机上的 java 程序,需要安装jstatd。
    对于具有更严格的安全实践的网络产所而言,可能使用一个自定义的策略文件来显示对特定的可信主机或网络的访问,尽管这种技术容易受到IP地址欺诈攻击。

jstat 查看JVM统计信息

基本情况

jstat (JVM Statistics Monitoring Tool):用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。

在没有GUI图形界面,只提供纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。常用于检测垃圾回收问题以及内存泄漏问题。

基本语法

它的基本使用语法为:

jstat -

查看命令相关参数:jstat -h 或 jstat -help

  1. 选项option可以由以下值构成。

    1. 类装载相关的:
      • class: 显示ClassLoader的相关信息:类的装载、卸载数量、总空间、类装载所消耗的时间等。
        JVM监控及诊断工具(命令行)_第1张图片
        这里显示了,加载的类的个数,加载类的字节数,卸载类的个数以及卸载类的字节数,最后是耗时字段。
    2. 垃圾回收相关的:
      1. -gc:显示与GC相关的堆信息。包括Eden区、两个Survivor区,老年代,永久代等的容量,已用空间、GC时间合计等信息。
        在这里插入图片描述
        S0C:幸存者0区
        S1C:幸存者1区
        S0U:幸存者0区已经使用的容量
        S1C:幸存者1区以及使用的容量
        EC:伊甸园区总容量
        EU:伊甸园区已经使用的容量
        OC:老年代的容量
        OU:老年代已经使用的容量
        MC:方法区的容量
        MU:方法区已经使用的容量
        CCSC:压缩类的容量
        CCSU:压缩类已经使用的容量
        YGC:发生Young GC的次数
        YGCT:发生Young GC所用的时间
        FGC: 发生Full GC的次数
        FGCT:发生Full GC所用的时间
        GCT:总的GC所用的时间

      2. -gccapacity:显示内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间。

      3. -gcutil:显示内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比。

      4. -gccause:与-gcutil功能一样,但是会额外输出导致最后一次或当前正发生的GC产生的原因。

      5. -gcnew:显示新生代 GC状况

      6. -gcnewcapacity:显示内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间

      7. -gcold:显示老年代GC状况

      8. -gcoldcapacity:显示内容与-gcold基本相同,输出主要关注使用到的最大、最小空间

      9. -gcpermcapacity:显示永久代使用到的最大、最小空间

    3. JIT相关的:
      1. -compiler: 显示JIT编译器编译过的方法、耗时等信息。
        在这里插入图片描述
      2. -printcompilation:输出已经被JIT编译的方法
        在这里插入图片描述
  2. interval:用于指定输出统计数据的周期,单位为毫秒。即:查询间隔
    JVM监控及诊断工具(命令行)_第2张图片

  3. count参数,用于指定查询的总次数

在这里插入图片描述
4. -t参数,可以在输出信息前加上一个Timestap列,显示程序的运行时间。单位是秒
在这里插入图片描述
5. -h参数,可以在周期性输出时,输出多少行数据后输出一个表头信息
JVM监控及诊断工具(命令行)_第3张图片

jinfo 实时查看和配置JVM的配置参数

基本情况

jinfo(Configuration Info for Java)
查看虚拟机配置参数,也可用于调整虚拟机的配置参数。
在很多情况下,Java应用程序不会指定所有的Java虚拟机参数。而此时,开发人员可能不知道某一个具体的Java虚拟机参数的默认值。在这种情况下,可能需要通过查找文档获取某个参数的默认值。这个查找过程可能是非常艰难的。但是有了jinfo工具,开发人员可以很方便地找到Java虚拟机参数的当前值。
JVM监控及诊断工具(命令行)_第4张图片

查看命令
  1. jinfo -sysprops PID 可以查看由System.getProperties()取得的参数。
  2. jinfo -flags PID 查看曾经赋过值的一些参数
    在这里插入图片描述
  3. jinfo -flag 具体参数 PID 查看某个java进程的具体参数的值
修改命令

其实,具体能够修改的参数很少。可以查看被标记为manageable的参数
JVM监控及诊断工具(命令行)_第5张图片

  1. 针对boolean类型
    jinfo -flag [+|-]具体参数 PID
    
  2. 针对非boolean类型
    jinfo -flag 具体参数=具体参数值 PID
    
拓展
  1. 查看所有JVM参数的初始值
    java -XX:+PrintFlagsInitial
    
  2. 查看所有JVM参数的最终值
    java -XX:+PrintFlagsFinal
    
  3. 查看哪些已经被用户或者JVM设置过的详细的XX参数的名称和值
    java -XX:+PrintCommandLineFlags
    

jmap 导出内存映像文件&内存使用情况

基本情况

jmap(JVM Memory Map):作用一方面是获取dump文件(堆转储快照文件,二进制文件),它还可以获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息等。

开发人员可以在控制台中输入命令“jmap -help”查阅jmap工具的具体使用方式和一些标准选项配置。

jmap -help
Usage:
    jmap [option] <pid>
        (to connect to running process)
    jmap [option] <executable <core>
        (to connect to a core file)
    jmap [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)

where <option> is one of:
    <none>               to print same info as Solaris pmap
    -heap                to print java heap summary
    -histo[:live]        to print histogram of java object heap; if the "live"
                         suboption is specified, only count live objects
    -clstats             to print class loader statistics
    -finalizerinfo       to print information on objects awaiting finalization
    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
    -F                   force. Use with -dump:<dump-options> <pid> or -histo
                         to force a heap dump or histogram when <pid> does not
                         respond. The "live" suboption is not supported
                         in this mode.
    -h | -help           to print this help message
    -J<flag>             to pass <flag> directly to the runtime system
基本语法
  1. -dump 生成java堆转储快照dump文件,特别地,-dump:live只保存堆中的存活对象
  2. -heap 输出整个堆空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用信息等
  3. -histo 输出堆中对象的统计信息,包括类、实例数量和合计容量。特别地,-histo:live只统计堆中的存活对象
导出内存映像文件
  1. 手动方式
    jmap -dump:format=b,file=<filename.hprof> <pid>
    jmap -dump:live,format=b,file=<filename.hprof> <pid>
    
    由于jmap将访问堆中的所有对象,为了保证在此过程中不被应用线程干扰,jmap需要借助安全点,让所有线程停留在不改变堆中数据的状态。也就是说,由jmap导出的堆快照必定是安全点位置的。这可能导致基于该堆快照的分析结果存在偏差。

假设在编译生成的机器码中,某些对象的生命周期在两个安全点之间,那么:live选项将无法探知到这些对象。另外,如果某个线程长时间无法跑到安全点,jmap将一直等下去。与前面讲的jstat则不同,垃圾回收器会主动将jstat所需要的摘要数据保存至固定位置之上,而jstat只需要直接读取即可。

  1. 自动方式
    当程序发生OOM退出系统时,一些瞬时信息都随着程序的终止而消失,而重写OOM问题往往比较困难或者耗时。此时若能在OOM时,自动导出dump文件就会显得非常迫切。
    -XX:+HeapDumpOnOutOfMemoryError
    -XX:HeapDumpPath=<filename.hprof>
    
显示堆内存相关的信息
  1. jmap -heap pid 显示命名执行这一刻,堆空间的占用情况
  2. jmap -histo pid JVM对象相关的信息
其他
  1. jmap -permstat pid 查看系统的ClassLoader信息(永久代)
  2. jmap -finalizerinfo 查看堆积在finalizer队列中的对象

jhat JDK自带的堆分析工具

jhat (JVM Heap Analysis Tool):JDK提供的jhat命令与jmap命令搭配使用,用于分析jmap生成的heap dump文件(堆转储快照)。jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,用户可以在浏览器中查看分析结果(分析虚拟机转储快照信息)。

使用jhat命令,就启动了一个http服务器,端口是7000,即http://localhost:7000/,就可以在浏览器里分析。说明:jhat命令在JDK9、JKD10中已经被删除,官方建议使用VisualVM代替。

jstack 打印JVM中线程快照

jstack (JVM Stack Trace):用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)。线程快照就是当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合。

生成线程快照的作用:用于定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待问题。这些都是导致线程长时间停顿的常见原因。当线程出现停顿时,就可以用jstack显示各个线程调用的堆栈情况。

在thread dump中,要留意下面几种状态

  • 死锁,Deadlock(重点关注)
  • 等待资源,Waiting on condition(重点关注)
  • 等待获取监视器,Waiting on monitor entry(重点关注)
  • 阻塞,Blocked(重点关注)
  • 执行中,Runnable
  • 暂停,Suspended

用法:jstack pid
参数:
-F 当正常输出的请求不被响应时,强制输出线程堆栈
-l 除堆栈外,显示关于锁的附加信息
-m 如果调用到本地方法的话,可以显示C/C++的堆栈

jcmd

在JDK1.7以后,新增了一个命令行工具jcmd。
它是一个多功能的工具,可以用来实现前面除了jstat 之外的所有命令的功能。比如:用它来导出堆、内存使用、查看Java进程、导出线程信息、执行GC、JVM运行时间等。

jcmd拥有jmap的大部分功能,并且在Oracle的官方网站上也推荐使用jcmd命令代替jmap命令

基本语法
  1. jcmd -l 列出所有的JVM进程
  2. jcmd pid help 针对指定的进程,列出支持的所有命令
  3. jcmd pid 具体命令

你可能感兴趣的:(JVM,java,开发语言,后端,jvm)