jmap 的作用并不仅仅是为了获取 dump 文件,它还可以查询 finalizer 执行队列、Java 堆和永久代的详细信息,如空间使用率、当前使用的是哪种收集器等。和jinfo一样,jmap有不少功能在 Windows 平台下也是受限制的。
示例:将指定应用程序的堆快照输出到桌面。后面,可以通过 jhat、Visual VM 等工具分析该堆文件。
C:\\Users\\SnailClimb>jmap -dump:format=b,file=C:\\Users\\SnailClimb\\Desktop\\heap.hprof 17340Dumping heap to C:\\Users\\SnailClimb\\Desktop\\heap.hprof ...Heap dump file created
C:\\Users\\SnailClimb>jhat C:\\Users\\SnailClimb\\Desktop\\heap.hprofReading from C:\\Users\\SnailClimb\\Desktop\\heap.hprof...Dump file created Sat May 0412:30:31 CST 2019Snapshot read, resolving...Resolving 131419 objects...Chasing references, expect 26 dots..........................Eliminating duplicate references..........................Snapshot resolved.Started HTTP server on port 7000Server is ready.
6. jstack :生成虚拟机当前时刻的线程快照
jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合.
Thread[线程 1,5,main]get resource1Thread[线程 2,5,main]get resource2Thread[线程 1,5,main]waiting get resource2Thread[线程 2,5,main]waiting get resource1
线程 A 通过 synchronized (resource1) 获得 resource1 的监视器锁,然后通过Thread.sleep(1000);让线程 A 休眠 1s 为的是让线程 B 得到执行然后获取到 resource2 的监视器锁。线程 A 和线程 B 休眠结束了都开始企图请求获取对方的资源,然后这两个线程就会陷入互相等待的状态,这也就产生了死锁。
Found one Java-level deadlock:============================="线程 2": waiting to lock monitor 0x000000000333e668 (object 0x00000000d5efe1c0, a java.lang.Object), which is held by "线程 1""线程 1": waiting to lock monitor 0x000000000333be88 (object 0x00000000d5efe1d0, a java.lang.Object), which is held by "线程 2"Java stack information for the threads listed above:==================================================="线程 2": at DeadLockDemo.lambda$main$1(DeadLockDemo.java:31) - waiting to lock <0x00000000d5efe1c0> (a java.lang.Object) - locked <0x00000000d5efe1d0> (a java.lang.Object) at DeadLockDemo$$Lambda$2/1078694789.run(Unknown Source) at java.lang.Thread.run(Thread.java:748)"线程 1": at DeadLockDemo.lambda$main$0(DeadLockDemo.java:16) - waiting to lock <0x00000000d5efe1d0> (a java.lang.Object) - locked <0x00000000d5efe1c0> (a java.lang.Object) at DeadLockDemo$$Lambda$1/1324119927.run(Unknown Source) at java.lang.Thread.run(Thread.java:748)Found 1 deadlock.
可以看到 jstack 命令已经帮我们找到发生死锁的线程的具体信息。
二、JDK 可视化分析工具
1. JConsole:Java 监视与管理控制台
JConsole 是基于 JMX 的可视化监视、管理工具。可以很方便的监视本地及远程服务器的 java 进程的内存使用情况。你可以在控制台输出console命令启动或者在 JDK 目录下的 bin 目录找到jconsole.exe然后双击启动。
①. 连接 Jconsole
如果需要使用 JConsole 连接远程进程,可以在远程 Java 程序启动时加上下面这些参数:
-Djava.rmi.server.hostname=外网访问 ip 地址 -Dcom.sun.management.jmxremote.port=60001//监控的端口号-Dcom.sun.management.jmxremote.authenticate=false //关闭认证-Dcom.sun.management.jmxremote.ssl=false
在使用 JConsole 连接时,远程进程地址如下:
外网访问 ip 地址:60001
②. 内存监控
JConsole 可以显示当前内存的详细信息。不仅包括堆内存/非堆内存的整体信息,还可以细化到 eden 区、survivor 区等的使用情况,如下图所示。
点击右边的“执行 GC(G)”按钮可以强制应用程序执行一个 Full GC。
新生代 GC(Minor GC):指发生新生代的的垃圾收集动作,Minor GC 非常频繁,回收速度一般也比较快。 老年代 GC(Major GC/Full GC):指发生在老年代的 GC,出现了 Major GC 经常会伴随至少一次的 Minor GC(并非绝对),Major GC 的速度一般会比 Minor GC 的慢 10 倍以上。