Java虚拟机五:常用内存分析命令和工具

一、常用命令

1、jps

  jps(JVM Process Status),可以列出虚拟机内的进程,并显示虚拟机执行主类名称以及这些进程的本地虚拟机唯一ID,该ID与操作系统的进程ID一致,jps命令格式为:  jps [options] [hostid] 

  其中options为该命令的选项,hostid为虚拟机中进程的唯一ID,也是linux下系统中进程的pid,options有如下取值:

选项 说明
-q 只显示进程id,不显示主类
-m 输出虚拟机进程启动时传递给主类的参数
-l 列出主类的全名,如果进程执行的是Jar包,则列出Jar包的路径
-v 输出虚拟机进程启动时候的参数

  命令示例如下:

[root@localhost software]# jps
74946 Jps
65684 Bootstrap
[root@localhost software]# jps -q
65684
75052
[root@localhost software]# jps -l
65684 org.apache.catalina.startup.Bootstrap
75160 sun.tools.jps.Jps
[root@localhost software]# jps -m
75298 Jps -m
65684 Bootstrap start
[root@localhost software]# jps -v
65684 Bootstrap -Djava.util.logging.config.file=/usr/local/tomcat8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -Dcatalina.base=/usr/local/tomcat8 -Dcatalina.home=/usr/local/tomcat8 -Djava.io.tmpdir=/usr/local/tomcat8/temp
75628 Jps -Denv.class.path=/usr/local/jdk/lib/ -Dapplication.home=/usr/local/jdk -Xms8m
[root@localhost software]# 

 

 2、jstat

  jstat(JVM Statistics Monitoring Tool)命令主要用来监控虚拟机运行状态信息,其命令格式为 jstat [options] [vmid] [interval[m|ms]] [count] 

  其中,options选项用来确定需要监视虚拟机的哪部分数据,vmid为本地虚拟机进程id,interval用于控制监控的时间间隔,可以加m|ms单位,count用来控制监控的次数。options选项取值如下:

选项 说明
-class 监控类装载,卸载数量,总空间以及类装载所耗费的时间
-gc 监视Java堆状况,包括Eden区,两个Survivor区,老年代等的容量,已用空间,GC时间合计等信息
-gccapacity 监视内容与-gc一样,但只要关注Java堆中各个区域使用到的最大,最小空间
-gcutil 监视内容与-gc一样,但只要关注已使用空间占总空间的百分比
-gccause 与-gcutil功能一样,但会额外输出导致上一次GC的原因
-gcnew 监视新生代GC状况
-gcnewcapacity 监视内容与-gcnew一样,但是主要关注使用新生代使用的最大,最小空间
-gcold 监视老年代GC状况
-gcoldcapacity 监视内容与-gcold一样,但是主要关注老年代使用的最大,最小空间
-compiler 输出JIT编译器编译过的方法,耗时等信息
-printcompilation 输出已经被JIT编译的方法

  命令示例如下:

[root@localhost software]# jstat -gc 65684 1s 2
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
704.0  704.0   0.0    0.0    6016.0   1369.2   14820.0     6365.8   18176.0 17511.6 2048.0 1922.7     12    0.134   2      0.392    0.526
704.0  704.0   0.0    0.0    6016.0   1369.2   14820.0     6365.8   18176.0 17511.6 2048.0 1922.7     12    0.134   2      0.392    0.526
[root@localhost software]# jstat -gcold 65684 1s 2
   MC       MU      CCSC     CCSU       OC          OU       YGC    FGC    FGCT     GCT   
 18176.0  17511.6   2048.0   1922.7     14820.0      6365.8     12     2    0.392    0.526
 18176.0  17511.6   2048.0   1922.7     14820.0      6365.8     12     2    0.392    0.526
[root@localhost software]# 

3、jmap

  jmap命令的主要作用是生成堆转储文件,其命令格式为: jmap [option] vmid 

  其中,option的取值有如下几种:

选项 说明
-dump 用于生成堆转储快照文件,命令格式为:jmap -dump:[live,]format=b,file=<filename>,其中live参数表示只dump出存活的对象,命令示例: jmap -dump:format=b,file=./result.hprof 65684 ;或者 jmap -dump:live,format=b,file=./result.hprof 65684 
-finalizerinfo 显示在F-QUeue中等待Finalizer线程执行finalize方法的对象,如: jmap -finalizerinfo 65684 
-heap 显示Java堆详细信息,如使用哪种垃圾回收期,参数配置,分代状况等。如: jmap -heap 65684 
-histo 显示堆中对象统计信息,包括类,实例数量,合计容量。如: jmap -histo 65684 
-F 当虚拟机对-dump命令没有响应的时候,可以使用该参数强制生成dump文件

  常用例子:

  (1)生成dump文件:

[root@localhost software]# jmap -dump:format=b,file=./dumpresult.hprof 65684
Dumping heap to /software/dumpresult.hprof ...
Heap dump file created
[root@localhost software]# 

  (2)查看Java堆详细信息:

[root@localhost software]# jmap -heap 65684
Attaching to process ID 65684, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.211-b12

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 257949696 (246.0MB)
   NewSize                  = 5570560 (5.3125MB)
   MaxNewSize               = 85983232 (82.0MB)
   OldSize                  = 11206656 (10.6875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 6881280 (6.5625MB)
   used     = 1330704 (1.2690582275390625MB)
   free     = 5550576 (5.2934417724609375MB)
   19.338030133928573% used
Eden Space:
   capacity = 6160384 (5.875MB)
   used     = 1330704 (1.2690582275390625MB)
   free     = 4829680 (4.6059417724609375MB)
   21.60099110704787% used
From Space:
   capacity = 720896 (0.6875MB)
   used     = 0 (0.0MB)
   free     = 720896 (0.6875MB)
   0.0% used
To Space:
   capacity = 720896 (0.6875MB)
   used     = 0 (0.0MB)
   free     = 720896 (0.6875MB)
   0.0% used
tenured generation:
   capacity = 15175680 (14.47265625MB)
   used     = 6518560 (6.216583251953125MB)
   free     = 8657120 (8.256072998046875MB)
   42.953989541160595% used

13442 interned Strings occupying 1162192 bytes.
[root@localhost software]# 

4、jstack

  jstack用于生成虚拟机当前时刻的线程快照(threaddump文件),命令格式为 jstack [option] vmid 。

  其中option具体取值如下:

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

 

  使用 jstack -l 65684>./result.txt 命令,将线程堆栈保存到result.txt中进行分析

5.jcmd

  jcmd命令格式为 jcmd [vmid] [option] ,具体的option取值,可以使用 jcmd [vmid] help 命令查看:

[root@localhost software]# jcmd 65684 help
65684:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
VM.classloader_stats
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.finalizer_info
GC.heap_info
GC.run_finalization
GC.run
VM.uptime
VM.dynlibs
VM.flags
VM.system_properties
VM.command_line
VM.version
help

For more information about a specific command use 'help <command>'.
[root@localhost software]#

使用示例:使用jcmd打印NativeMemoryTracking,分析堆外内存

  首先需要配置JVM参数 -XX:NativeMemoryTracking=[off | summary | detail] 。在tomcat的 catalina.sh 中加入 JAVA_OPTS="-XX:NativeMemoryTracking=detail" ,然后使用命令 jcmd 112352 VM.native_memory summary 查看内存:

[root@localhost bin]# jcmd 112352 VM.native_memory summary
112352:

Native Memory Tracking:

Total: reserved=1614878KB, committed=85806KB
-                 Java Heap (reserved=251904KB, committed=16384KB)
                            (mmap: reserved=251904KB, committed=16384KB) 
 
-                     Class (reserved=1063348KB, committed=15412KB)
                            (classes #2372)
                            (malloc=436KB #2468) 
                            (mmap: reserved=1062912KB, committed=14976KB) 
 
-                    Thread (reserved=42331KB, committed=42331KB)
                            (thread #42)
                            (stack: reserved=42148KB, committed=42148KB)
                            (malloc=135KB #207) 
                            (arena=48KB #80)
 
-                      Code (reserved=250457KB, committed=5605KB)
                            (malloc=857KB #1584) 
                            (mmap: reserved=249600KB, committed=4748KB) 
 
-                        GC (reserved=836KB, committed=72KB)
                            (malloc=8KB #109) 
                            (mmap: reserved=828KB, committed=64KB) 
 
-                  Compiler (reserved=141KB, committed=141KB)
                            (malloc=10KB #89) 
                            (arena=131KB #5)
 
-                  Internal (reserved=783KB, committed=783KB)
                            (malloc=751KB #3761) 
                            (mmap: reserved=32KB, committed=32KB) 
 
-                    Symbol (reserved=4358KB, committed=4358KB)
                            (malloc=2848KB #17221) 
                            (arena=1511KB #1)
 
-    Native Memory Tracking (reserved=544KB, committed=544KB)
                            (malloc=118KB #1670) 
                            (tracking overhead=426KB)
 
-               Arena Chunk (reserved=176KB, committed=176KB)
                            (malloc=176KB) 
 
[root@localhost bin]# 

二、常用工具

  MAT(Eclipse Memory Analyzer )是一个Eclipse插件,可以在Eclipse中安装,也可以独立运行。使用MAT进行内存分析非常方便。其下载地址为:https://www.eclipse.org/mat/downloads.php

  选择合适的版本下载,解压后即可使用。

  要分析内存,首先要获取dump文件,可以通过配置JVM参数 -XX:+HeapDumpOnOutOfMemoryError ,让虚拟机在内存溢出的时候dump出内存快照,也可以使用 jmap -dump:format=b,file=./dumpresult.hprof 65684 命令随时dump出内存快照。

  打开MAT后,点击“Open a Heap Dump”选择dump文件,会弹出如下界面:

  

  选择“Leak Suspects Report”生成内存泄漏分析报告:

  

  MAT会以饼图的形式列出发生内存溢出时候,堆内存中占用内存最大的的几个对象。点击“Leak Suspects”查看内存泄漏分析报告:

  

  

  MAT分析结果认为导致内存泄漏的原因有两点,问题1大意是0xff993af0 http-nio-8080-exec-1这个线程持有的本地变量占用了50.20%的内存,点击Detail可以查看具体的分析结果:

  

  分析结果中列出了内存中对象统计结果,按照类进行统计的结果,可以看到有此时内存中共有com.demo.ssm.entity.User类的对象50428个,这些对象的保留堆大小为15,330,112kb。同时0xfe990000的这个Object中保存了56*20=1120个User对象,而这个Object是被0xffa65ff0这个ArrayList引用的,该Object和ArrayList占用堆内存50.18%。按照这些信息,排查代码中向ArrayList中添加User对象的操作,可以找出内存溢出的原因。

  关于MAT的使用要点,可以参考:https://eclipsesource.com/blogs/2013/01/21/10-tips-for-using-the-eclipse-memory-analyzer/

 

  

 

posted @ 2019-05-30 22:46  码农大卫  阅读(4291)  评论(0编辑  收藏  举报