jmap:导出内存映像文件&内存使用情况
基本情况
jmap(JVM Memory Map):一方法获取dump文件(堆转储快照文件,二进制文件),还可以获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息
基本语法
jmap [option] (to connect to running process) jmap [option] <executable (to connect to a core file) jmap [option] [server_id@] (to connect to remote debug server) option包括下表:
生成Java堆转储快照:dump文件 特别的:-dump:live只保存堆中的存活对象
输出整个堆空间的详细信息,包括GC的使用,堆配置信息以及内存使用信息
输出堆空间中对象的统计信息,包括类,实例数量和合计容量
以ClassLoader为统计口径输出永久代的内存状态信息
显示在F-Queue中等待Finalizer线程执行finalize方法的对象
当虚拟机进程对-dump选项没有任何响应时,强制执行生成dump文件
导出内存映射文件
将堆中所有存活对象导出至一个文件之中 Heap Dump又叫堆存储文件,指一个Java进程在某个时间点的内存快照,Heap Dump在触发内存快照的时候会保存此该的信息
All Objects All Classes Garbage Collection Roots Thread Stacks and Local Variables ①通常在写Heap Dump文件前会触发一次Full GC,所以heap dump文件里保存的都是Full GC后留下的对象信息 ②由于生成dump文件比较耗时,需要耐心等待,尤其大内存镜像生成dump文件,则需要耗费更长的时间来完成
jmap -dump:format=b,file=<filename.hprof> 注:format=b表示采用图形化工具能打开对应的hprof文件 jmap -dump:live,format=b,file=<filename.hprof>
当程序发生OOM退出系统时,一些瞬时停止都随着程序的终止而消失,而重现OOM问题往往比较困难或者耗时,此时若能在OOM时,自动导出dump文件就显得很重要 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<filename.hprof>
显示堆内存相关信息
-heap pid:程序运行时 -histo pid
其它作用
-pemstat pid :查看系统的ClassLoader信息–linux环境下 -finzlizerinfo:查看堆积在finalizer队列中的对象–linux环境下
总结
由于jmap将访问堆中的所有对象,为了保证在此过程中不被应用线程干扰,jmap需要借助安全点机制 ,让所有线程停留在不改变堆中数据的状态,由jmap导出的堆快照必定是安全点位置的,这可能导致基于该堆快照的分析结果存在偏差 举个例子:假设在编译生成的机器码中,某些对象的生命周期在两个安全点之间,那么:live选项将无法探知到这些对象 如果某个线程长时间无法跑到安全点,jmap将一直等下去,与前面的jstat不同,垃圾回收器会主动将jstat所需要的摘要数据保存至固定位置之中,而jstat只需直接读取即可
jhat(JVM Heap Analysis Tool)
Sun JDK提供了jhat与jmap命令搭配使用,用于分析jmap生成的heap dump文件,jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,用户可以在浏览器中查看分析结果 使用了jhat命令,就启动了一个http服务,端口7000,通过在浏览器中输入http://localhost:7000获取分析结果 jhat在jdk9,10中已经被删除,官方建议VisualVM代替
-stack false | true:关闭 | 打开对象分配调用栈跟踪 -refs false | true : 关闭 | 打开对象引用跟踪 -port port-number 设置jhat HTTP Server端口,默认7000 -exclude exclude-file:执行对象查询时需要排除的数据成员 -baseline exclude-file:指定一个基准堆转储 -debug int:设置Debug级别 -version:启动后显示版本信息就退出 -J :传入启动参数,
jstack(JVM Stack Trace)
用于生成虚拟机指定进程当前时刻的线程快照,线程快照是当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合 生成线程快照的作用:可用于定位线程出现长时间停顿的原因,如线程间死锁、死循环,请求外部资源导致的长时间等待等问题,这些都是导致线程长时间停顿的常见原因,当线程出现停顿时,就可以用jstack显示各个线程调用的堆栈情况 在thread dump中,要留意以下几种状态
死锁,Deadlock 等待资源,Waiting on condition 等待获取监视器,Waiting on monitor entry 阻塞,Blocked 执行中,Runnable 暂停,Suspended
package com. chapter12 ;
public class ThreadDeadLock { public static void main ( String [ ] args) { StringBuilder s1 = new StringBuilder ( ) ; StringBuilder s2 = new StringBuilder ( ) ; new Thread ( ) { @Override public void run ( ) { synchronized ( s1) { try { Thread . sleep ( 100 ) ; } catch ( InterruptedException e) { e. printStackTrace ( ) ; } synchronized ( s2) { s1. append ( "b" ) ; s2. append ( "2" ) ; System . out. println ( s1) ; System . out. println ( s2) ; } } } } . start ( ) ; new Thread ( ) { @Override public void run ( ) { synchronized ( s2) { try { Thread . sleep ( 100 ) ; } catch ( InterruptedException e) { e. printStackTrace ( ) ; } synchronized ( s1) { s1. append ( "d" ) ; s2. append ( "4" ) ; System . out. println ( s1) ; System . out. println ( s2) ; } } } } . start ( ) ; }
}
C : \Users \Administrator \IdeaProjects \jvm> jstack 12840
执行结果:
Found one Java - level deadlock:
== == == == == == == == == == == == == == =
"Thread-1" : waiting to lock monitor 0x0000000002d0b288 ( object 0x000000071649ee08 , a java. lang. StringBuilder) , which is held by "Thread-0"
"Thread-0" : waiting to lock monitor 0x0000000002d0c728 ( object 0x000000071649ee50 , a java. lang. StringBuilder) , which is held by "Thread-1" Java stack information for the threads listed above:
== == == == == == == == == == == == == == == == == == == == == == == == == =
"Thread-1" : at com. chapter12. ThreadDeadLock $2. run ( ThreadDeadLock . java: 40 ) - waiting to lock < 0x000000071649ee08> ( a java. lang. StringBuilder) - locked < 0x000000071649ee50> ( a java. lang. StringBuilder)
"Thread-0" : at com. chapter12. ThreadDeadLock $1. run ( ThreadDeadLock . java: 22 ) - waiting to lock < 0x000000071649ee50> ( a java. lang. StringBuilder) - locked < 0x000000071649ee08> ( a java. lang. StringBuilder) Found 1 deadlock.
public class ThreadSleepTest { public static void main ( String [ ] args) { System . out. println ( "hello - 1" ) ; try { Thread . sleep ( 1000 * 60 * 10 ) ; } catch ( InterruptedException e) { e. printStackTrace ( ) ; } System . out. println ( "hello - 2" ) ; }
}
>> jstack 920
"main" #1 prio= 5 os_prio= 0 tid= 0x00000000036d2800 nid= 0x1cb0 waiting on condition [ 0x000000000320f000 ] java. lang. Thread. State: TIMED_WAITING ( sleeping) at java. lang. Thread. sleep ( Native Method ) at com. chapter12. ThreadSleepTest. main ( ThreadSleepTest . java: 12 )
class Number implements Runnable { private int number = 1 ; @Override public void run ( ) { while ( true ) { synchronized ( this ) { if ( number <= 100 ) { try { Thread . sleep ( 500 ) ; } catch ( InterruptedException e) { e. printStackTrace ( ) ; } System . out. println ( Thread . currentThread ( ) . getName ( ) + ":" + number) ; number++ ; } else { break ; } } } }
}
public class ThreadSyncTest { public static void main ( String [ ] args) { Number number = new Number ( ) ; Thread t1 = new Thread ( number) ; Thread t2 = new Thread ( number) ; t1. setName ( "线程1" ) ; t2. setName ( "线程2" ) ; t1. start ( ) ; t2. start ( ) ; }
}
"线程2" #12 prio= 5 os_prio= 0 tid= 0x0000000027b56800 nid= 0x3380 waiting on condition [ 0x000000002879f000 ] java. lang. Thread. State: TIMED_WAITING ( sleeping) at java. lang. Thread. sleep ( Native Method ) at com. chapter12. Number. run ( ThreadSyncTest . java: 15 ) - locked < 0x00000007164a1960> ( a com. chapter12. Number) at java. lang. Thread. run ( Thread . java: 748 ) "线程1" #11 prio= 5 os_prio= 0 tid= 0x0000000027b4d800 nid= 0x1d18 waiting for monitor entry [ 0x000000002869f000 ] java. lang. Thread. State: BLOCKED ( on object monitor) at com. chapter12. Number. run ( ThreadSyncTest . java: 13 ) - waiting to lock < 0x00000007164a1960> ( a com. chapter12. Number) at java. lang. Thread. run ( Thread . java: 748 )
-F:当正常输出的请求不被响应时,强制输出线程堆栈 -l:除堆栈外,显示关于锁的附加信息 -m:如果调用到本地方法的话,可以显示C/C++堆栈 -h:帮助操作
jcmd
基本情况
它是一个多功能工具,可以实现除了jstat之外所有命令的功能,用它来导出堆、内存使用、查看Java进程、导出线程信息、执行GC、JVM运行时间等
基本语法
-l:列出所有的JVM进程 pid help:针对指定的进程, pid 具体命令