JVM调优-常用命令使用

By timebusker on February 15, 2019

运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多: jconsole、大名鼎鼎的VisualVM,IBM的Memory Analyzer等等,但是在生产环境出现问题的时候,一方面工具的使用会有所限制, 另一方面喜欢装X的我们,总喜欢在出现问题的时候在终端输入一些命令来解决。所有的工具几乎都是依赖于jdk的接口和底层的这些命令, 研究这些命令的使用也让我们更能了解jvm构成和特性。

Sun JDK监控和故障处理命令有jps、jstat、jmap、jhat、jstack、jinfo下面做一一介绍

jinfo

jinfo(JVM Configuration info)这个命令作用是实时查看和调整虚拟机运行参数。 之前的jps -v口令只能查看到显示指定的参数,如果想要查看未被显示指定的参数的值就要使用jinfo口令。

命令格式:jinfo [option] [args] LVMID

option参数

  • -flag : 输出指定args参数的值
  • -flags : 不需要args参数,输出所有JVM参数的值
  • -sysprops : 输出系统属性,等同于System.getProperties()

jps

jps(JVM Process Status Tool),显示指定系统内所有的HotSpot虚拟机进程。

命令格式:jps [options] [hostid],其中[option]、[hostid]参数也可以不写。

option参数:

  • -l : 输出主类全名或jar路径
  • -q : 只输出LVMID
  • -m : 输出JVM启动时传递给main()的参数
  • -v : 输出JVM启动时显示指定的JVM参数

jstat

jstat(JVM statistics Monitoring)是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。

命令格式:jstat [option] LVMID [interval] [count]

  • [option] : 操作参数
  • LVMID : 本地虚拟机进程ID
  • [interval] : 连续输出的时间间隔
  • [count] : 连续输出的次数

option 参数总览: image

option 参数详解:

  • -class:监视类装载、卸载数量、总空间以及耗费的时间

image

> Loaded : 加载class的数量
> Bytes : class字节大小
> Unloaded : 未加载class的数量
> Bytes : 未加载class的字节大小
> Time : 加载时间
  • -compiler : 输出JIT编译过的方法数量耗时等

image

> Compiled : 编译数量
> Failed : 编译失败数量
> Invalid : 无效数量
> Time : 编译耗时
> FailedType : 失败类型
> FailedMethod : 失败方法的全限定名
  • -gc 垃圾回收堆的行为统计,常用命令
    image
    C即Capacity 总容量,U即Used 已使用的容量

    S0C : survivor0区的总容量 S1C : survivor1区的总容量 S0U : survivor0区已使用的容量 S1C : survivor1区已使用的容量 EC : Eden区的总容量 EU : Eden区已使用的容量 OC : Old区的总容量 OU : Old区已使用的容量 PC 当前perm的容量 (KB) PU perm的使用 (KB) YGC : 新生代垃圾回收次数 YGCT : 新生代垃圾回收时间 FGC : 老年代垃圾回收次数 FGCT : 老年代垃圾回收时间 GCT : 垃圾回收总消耗时间

示例: jstat -gc 3916 2000 20
每隔2000ms输出1262的gc情况,一共输出20次

  • -gccapacity 同-gc,不过还会输出Java堆各区域使用到的最大、最小空间
    image

    NGCMN : 新生代占用的最小空间 NGCMX : 新生代占用的最大空间 OGCMN : 老年代占用的最小空间 OGCMX : 老年代占用的最大空间 OGC:当前年老代的容量 (KB) OC:当前年老代的空间 (KB) PGCMN : perm占用的最小空间 PGCMX : perm占用的最大空间

  • -gcutil 同-gc,不过输出的是已使用空间占总空间的百分比

image

  • -gccause 垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因

image

> LGCC:最近垃圾回收的原因
> GCC:当前垃圾回收的原因
  • -gcnew/gcold 统计新生代的行为/统计旧生代的行为
    image

    TT:Tenuring threshold(提升阈值) MTT:最大的tenuring threshold DSS:survivor区域大小 (KB)

  • -gcnewcapacity/gcoldcapacity 新生代与其相应的内存空间的统计/统计旧生代的大小和空间

image

> NGC:当前年轻代的容量 (KB)
> S0CMX:最大的S0空间 (KB)
> S0C:当前S0空间 (KB)
> ECMX:最大eden空间 (KB)
> EC:当前eden空间 (KB)
  • -printcompilation hotspot编译方法统计

image

> Compiled:被执行的编译任务的数量
> Size:方法字节码的字节数
> Type:编译类型
> Method:编译方法的类名和方法名。类名使用"/" 代替 "." 作为空间分隔符. 方法名是给出类的方法名. 格式是一致于HotSpot - XX:+PrintComplation 选项

jmap

jmap(JVM Memory Map)命令用于生成heap dump文件,如果不使用这个命令,还阔以使用-XX:+HeapDumpOnOutOfMemoryError参数来让虚拟机出现OOM的时候·自动生成dump文件。 jmap不仅能生成dump文件,还阔以查询finalize执行队列、Java堆和永久代的详细信息,如当前使用率、当前使用的是哪种收集器等。

命令格式:jmap [option] LVMID

  • option参数

    dump : 生成堆转储快照 finalizerinfo : 显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象 heap : 显示Java堆详细信息 histo : 显示堆中对象的统计信息 permstat : to print permanent generation statistics F : 当-dump没有响应时,强制生成dump快照

  • -dump 常用格式:-dump:live,format=b,file=<filename> pid
    jmap -dump:live,format=b,file=aaaaaaaaaaaaaaaaa.dmp 7180
    dump堆到文件,format指定输出格式,live指明是活着的对象,file指定文件名

  • -finalizerinfo 打印等待回收对象的信息
    image
    可以看到当前F-QUEUE队列中并没有等待Finalizer线程执行finalizer方法的对象。

  • -heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况,可以用此来判断内存目前的使用情况以及垃圾回收情况.
$ jmap -heap 7180
  Attaching to process ID 7180, please wait...
  Debugger attached successfully.
  Server compiler detected.
  JVM version is 24.71-b01  

  using thread-local object allocation.
  Parallel GC with 4 thread(s)//GC 方式  

  Heap Configuration: //堆内存初始化配置
     MinHeapFreeRatio = 0 //对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40)
     MaxHeapFreeRatio = 100 //对应jvm启动参数 -XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default 70)
     MaxHeapSize      = 2082471936 (1986.0MB) //对应jvm启动参数-XX:MaxHeapSize=设置JVM堆的最大大小
     NewSize          = 1310720 (1.25MB)//对应jvm启动参数-XX:NewSize=设置JVM堆的‘新生代’的默认大小
     MaxNewSize       = 17592186044415 MB//对应jvm启动参数-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小
     OldSize          = 5439488 (5.1875MB)//对应jvm启动参数-XX:OldSize=<value>:设置JVM堆的‘老生代’的大小
     NewRatio         = 2 //对应jvm启动参数-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
     SurvivorRatio    = 8 //对应jvm启动参数-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值 
     PermSize         = 21757952 (20.75MB)  //对应jvm启动参数-XX:PermSize=<value>:设置JVM堆的‘永生代’的初始大小
     MaxPermSize      = 85983232 (82.0MB)//对应jvm启动参数-XX:MaxPermSize=<value>:设置JVM堆的‘永生代’的最大大小
     G1HeapRegionSize = 0 (0.0MB)  

  Heap Usage://堆内存使用情况
  PS Young Generation
  Eden Space://Eden区内存分布
     capacity = 33030144 (31.5MB)//Eden区总容量
     used     = 1524040 (1.4534378051757812MB)  //Eden区已使用
     free     = 31506104 (30.04656219482422MB)  //Eden区剩余容量
     4.614088270399305% used //Eden区使用比率
  From Space:  //其中一个Survivor区的内存分布
     capacity = 5242880 (5.0MB)
     used     = 0 (0.0MB)
     free     = 5242880 (5.0MB)
     0.0% used
  To Space:  //另一个Survivor区的内存分布
     capacity = 5242880 (5.0MB)
     used     = 0 (0.0MB)
     free     = 5242880 (5.0MB)
     0.0% used
  PS Old Generation //当前的Old区内存分布
     capacity = 86507520 (82.5MB)
     used     = 0 (0.0MB)
     free     = 86507520 (82.5MB)
     0.0% used
  PS Perm Generation//当前的 “永生代” 内存分布
     capacity = 22020096 (21.0MB)
     used     = 2496528 (2.3808746337890625MB)
     free     = 19523568 (18.619125366210938MB)
     11.337498256138392% used  

  670 interned Strings occupying 43720 bytes.

可以很清楚的看到Java堆中各个区域目前的情况。

  • -histo 打印堆的对象统计,包括对象数、内存大小等等 (因为在dump:live前会进行full gc,如果带上live则只统计活对象,因此不加live的堆大小要大于加live堆的大小 )

image

B byte
C char
D double
F float
I int
J long
Z boolean
[ 数组,如[I表示int[]
[L+类名 其他对象

  • -F 强制模式。如果指定的pid没有响应,请使用jmap -dump或jmap -histo选项。此模式下,不支持live子选项。

jhat

jhat(JVM Heap Analysis Tool)命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看。在此要注意, 一般不会直接在服务器上进行分析,因为jhat是一个耗时并且耗费硬件资源的过程,一般把服务器生成的dump文件复制到本地或其他机器上进行分析。

命令格式:jhat [dumpfile]

jstack

jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合, 生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。 另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。

命令格式:jstack [option] LVMID

option参数

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