常见的Java诊断工具有以下几种:
- jps:显示出JVM进程号以及进程启动时的参数,可以快速的查询到Java有效进程。
使用说明:在命令行中输入jps即可输出JVM的进程号及其启动时传递给JVM的参数。
示例:
在命令行中输入jps,可以看到如下结果:
$ jps
71035 Jps
70926 Main
其中,第一行的71035表示jps进程的进程号;第二行的70926表示Main进程的进程号。
- jstack:用于获取Java进程中各线程的堆栈信息,可以帮助快速诊断正在运行的Java进程卡死的原因。
使用说明:在命令行中输入jstack和目标进程的进程号即可输出该进程各线程的堆栈信息。
示例:
假如我们要查找进程号为70926的Java进程当前线程状态,我们可以在命令行中输入以下命令:
$ jstack 70926
输出结果中,我们可以找到当前进程运行时JVM堆栈信息,例如:
$ jstack 70926
-----BEGIN JAVA STACK TRACE-----
"main" prio=5 tid=0x000000001801f800 nid=0x1f03 waiting on condition [0x000070000b5ee000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007c86f9900> (a java.util.concurrent.CountDownLatch$Sync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304)
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:629)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.toSend(QuorumCnxManager.java:546)
at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.process(FastLeaderElection.java:449)
at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.run(FastLeaderElection.java:420)
at java.lang.Thread.run(Thread.java:748)
"process reaper" daemon prio=10 tid=0x00007ffee6c77000 nid=0x3d07 waiting on condition [0x000070000c469000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007c871f4f0> (a java.util.concurrent.SynchronousQueue$TransferStack)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
...
其中,每一个线程对应一个线程状态。在这个例子中,我们可以看到线程”main”处于WAITING状态。如果需要更深入的分析,我们可以将这些信息通过其他工具进行分析,例如profiler,这里就不再赘述。