一般应用程序都部署在Linux服务器上,当然我们可以使用界面化的调优工具例如jconsole、VisualVM等进行远程连接来进行监控和性能分析,但归根结底,工具只是将指令执行的结果进行友好的展示而已,而且工具的使用终究还是有各种限制,所以我们必须掌握JVM的调优指令。
JVM的调优指令在安装JDK的bin目录下,如图:
这里主要介绍jps/jstat/jmap/jstack/jinfo这几个常用的指令,每个指令都可通过man来查看如何使用。
jps [option] [hostid]
option参数可输也可不输。
-l: 输出主类全名或jar路径
-q: 只输出LVMID
-m: 输出JVM启动时传递给main()的参数
-v: 输出JVM启动时显示指定的JVM参数
jstat [option] vmid [interval] [count]
参数:
option: 操作参数
vmid: 本地虚拟机进程ID
interval: 连续输出的时间间隔
count: 连续输出的次数
Option | Displays |
---|---|
class | class loader的行为统计。Statistics on the behavior of the class loader. |
compiler | HotSpt JIT编译器行为统计。Statistics of the behavior of the HotSpot Just-in-Time compiler. |
gc | 垃圾回收堆的行为统计。Statistics of the behavior of the garbage collected heap. |
gccapacity | 各个垃圾回收代容量(young,old,perm)和他们相应的空间统计。Statistics of the capacities of the generations and their corresponding spaces. |
gcutil | 垃圾回收统计概述。Summary of garbage collection statistics. |
gccause | 垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因。Summary of garbage collection statistics (same as -gcutil), with the cause of the last and |
gcnew | 新生代行为统计。Statistics of the behavior of the new generation. |
gcnewcapacity | 新生代与其相应的内存空间的统计。Statistics of the sizes of the new generations and its corresponding spaces. |
gcold | 年老代和永生代行为统计。Statistics of the behavior of the old and permanent generations. |
gcoldcapacity | 年老代行为统计。Statistics of the sizes of the old generation. |
gcpermcapacity | 永生代行为统计。Statistics of the sizes of the permanent generation. |
printcompilation | HotSpot编译方法统计。HotSpot compilation method statistics. |
下面是对一些常用的option参数的解释,注意92203是通过jps -l指令执行过程中得到的id,即我本地运行的Tomcat的id:
Compiled : 编译数量
Failed : 编译失败数量
Invalid : 无效数量
Time : 编译耗时
FailedType : 失败类型
FailedMethod : 失败方法的全限定名
Loaded : 加载class的数量
Bytes : class字节大小
Unloaded : 未加载class的数量
Bytes : 未加载class的字节大小
Time : 加载时间
jstat -gc 92203
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 : 垃圾回收总消耗时间
S0 : survivor0区的总容量
S1 : survivor1区的总容量
E : Eden区的总容量
O : Old区的总容量
OU : Old区已使用的容量
YGC : 新生代垃圾回收次数
YGCT : 新生代垃圾回收时间
FGC : 老年代垃圾回收次数
FGCT : 老年代垃圾回收时间
GCT : 垃圾回收总消耗时间
LGCC:最近垃圾回收的原因
GCC:当前垃圾回收的原因
NGCMN : 新生代占用的最小空间
NGCMX : 新生代占用的最大空间
OGCMN : 老年代占用的最小空间
OGCMX : 老年代占用的最大空间
OGC:当前年老代的容量 (KB)
OC:当前年老代的空间 (KB)
PGCMN : perm占用的最小空间
PGCMX : perm占用的最大空间
jmap [option] vmid
jmap(JVM Memory Map)命令用于生成heap dump文件,如果不使用这个命令,还可以使用-XX:+HeapDumpOnOutOfMemoryError参数来让虚拟机出现OOM时自动生成dump文件。jmap不仅能生成dump文件,还能查询finalize执行队列、Java堆和永久代的详细信息,如当前使用率、当前使用的是哪种收集器等。
参数:
dump : 生成堆转储快照
finalizerinfo : 显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象
heap : 显示Java堆详细信息
histo : 显示堆中对象的统计信息
permstat : to print permanent generation statistics
F : 当-dump没有响应时,强制生成dump快照
Attaching to process ID 94358, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.79-b02
using thread-local object allocation.
Parallel GC with 8 thread(s)
Heap Configuration: //堆内存初始化配置
MinHeapFreeRatio = 0 //jvm参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40)
MaxHeapFreeRatio = 100 //jvm参数 -XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default 70)
MaxHeapSize = 1073741824 (1024.0MB) //jvm参数-XX:MaxHeapSize=设置JVM堆的最大大小
NewSize = 536870912 (512.0MB)//jvm参数-XX:NewSize=设置JVM堆的‘新生代’的默认大小
MaxNewSize = 536870912 (512.0MB)//jvm参数-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小
OldSize = 5439488 (5.1875MB) //参数-XX:OldSize=:设置JVM堆的‘老生代’的大小
NewRatio = 2 //参数-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
SurvivorRatio = 8 //参数-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值
PermSize = 536870912 (512.0MB) //参数-XX:PermSize=:设置JVM堆的‘永生代’的初始大小
MaxPermSize = 1073741824 (1024.0MB)//参数-XX:MaxPermSize=:设置JVM堆的‘永生代’的最大大小
G1HeapRegionSize = 0 (0.0MB)
Heap Usage: //堆内存使用情况
PS Young Generation
Eden Space:
capacity = 300417024 (286.5MB) //总容量
used = 231151904 (220.44363403320312MB) //已使用
free = 69265120 (66.05636596679688MB)//剩余容量
76.94367680041994% used //Eden区使用比率
From Space: // S0 内存使用情况
capacity = 120586240 (115.0MB)
used = 53528904 (51.04914093017578MB)
free = 67057336 (63.95085906982422MB)
44.39055733058763% used
To Space: // S1 内存使用情况
capacity = 115867648 (110.5MB)
used = 0 (0.0MB)
free = 115867648 (110.5MB)
0.0% used
PS Old Generation // Old区使用情况
capacity = 536870912 (512.0MB)
used = 241598968 (230.40673065185547MB)
free = 295271944 (281.59326934814453MB)
45.00131458044052% used
PS Perm Generation // 永久代使用情况
capacity = 536870912 (512.0MB)
used = 143245904 (136.6099395751953MB)
free = 393625008 (375.3900604248047MB)
26.681628823280334% used
18942 interned Strings occupying 2284376 bytes.
也可以使用dump参数,将dump文件保存到本地,然后再通过工具来分析。
-dump::live,format=b,file= pid
$ ./jmap -dump:live,format=b,file=/tmp/myDump.hprof 94358
Dumping heap to /private/tmp/myDump.hprof ...
Heap dump file created
jhat [dumpfile]
jhat(JVM Heap Analysis Tool)命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看。在此要注意,一般不会直接在服务器上进行分析,因为jhat是一个耗时并且耗费硬件资源的过程,一般把服务器生成的dump文件复制到本地或其他机器上进行分析。
-stack false|true 关闭对象分配调用栈跟踪(tracking object allocation call stack)。 如果分配位置信息在堆转储中不可用. 则必须将此标志设置为 false. 默认值为 true.>
-refs false|true 关闭对象引用跟踪(tracking of references to objects)。 默认值为 true. 默认情况下, 返回的指针是指向其他特定对象的对象,如反向链接或输入引用(referrers or incoming references), 会统计/计算堆中的所有对象。>
-port port-number 设置 jhat HTTP server 的端口号. 默认值 7000.>
-exclude exclude-file 指定对象查询时需要排除的数据成员列表文件(a file that lists data members that should be excluded from the reachable objects query)。 例如, 如果文件列列出了 java.lang.String.value , 那么当从某个特定对象 Object o 计算可达的对象列表时, 引用路径涉及 java.lang.String.value 的都会被排除。>
-baseline exclude-file 指定一个基准堆转储(baseline heap dump)。 在两个 heap dumps 中有相同 object ID 的对象会被标记为不是新的(marked as not being new). 其他对象被标记为新的(new). 在比较两个不同的堆转储时很有用.>
-debug int 设置 debug 级别. 0 表示不输出调试信息。 值越大则表示输出更详细的 debug 信息.>
-version 启动后只显示版本信息就退出>
-J< flag > 因为 jhat 命令实际上会启动一个JVM来执行, 通过 -J 可以在启动JVM时传入一些启动参数. 例如, -J-Xmx512m 则指定运行 jhat 的Java虚拟机使用的最大堆内存为 512 MB. 如果需要使用多个JVM启动参数,则传入多个 -Jxxxxxx.
示例:
中间的-J-Xmx1024m是在dump快照很大的情况下分配512M内存去启动HTTP服务器,运行完之后就可在浏览器打开Http://localhost:7000进行快照分析 堆快照分析主要在最后面的Heap Histogram里,里面根据class列出了dump的时候所有存活对象。
jstat [dumpfile]
jstack主要用于生成JVM当前时刻的线程快照。线程快照就是指JVM内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现挂起的状态,jstack是非常有用的。
-F : 当正常输出请求不被响应时,强制输出线程堆栈
-l : 除堆栈外,显示关于锁的附加信息
-m : 如果调用到本地方法的话,可以显示C/C++的堆栈
示例:
详细分析可看下这篇文章:Java命令学习系列(二)——Jstack