使用ps -eL
or top -H -p <pid>
,或者如果您需要实时查看和监控,请运行 top(然后 shift H),以获取与 java 进程关联的轻量级进程(LWP aka 线程)。
root@xxx:/# ps -eL
PID LWP TTY TIME CMD
1 1 ? 00:00:00 java
1 7 ? 00:00:01 java
1 8 ? 00:07:52 java
1 9 ? 00:07:52 java
1 10 ? 00:07:51 java
1 11 ? 00:07:52 java
1 12 ? 00:07:52 java
1 13 ? 00:07:51 java
1 14 ? 00:07:51 java
1 15 ? 00:07:53 java
…
1 164 ? 00:00:02 java
1 166 ? 00:00:02 java
1 169 ? 00:00:02 java
注意 LWP=轻量级进程;在 Linux 中,线程与进程相关联,以便在内核中对其进行管理;LWP 与父进程共享文件和其他资源。现在让我们看看最耗时的线程
1 8 ? 00:07:52 java
1 9 ? 00:07:52 java
1 10 ? 00:07:51 java
1 11 ? 00:07:52 java
1 12 ? 00:07:52 java
1 13 ? 00:07:51 java
1 14 ? 00:07:51 java
1 15 ? 00:07:53 java
Jstack是一个打印 Java Stack 的 JDK 实用程序;它打印表单的线程。
熟悉其他很酷的 JDK 工具(jcmd jstat jhat jmap jstack等 — https://docs.oracle.com/javase/8/docs/technotes/tools/unix/)
jstack -l <process id>
堆栈跟踪中的 nid,本机线程 id 是连接到 linux 中的 LWT 的那个(https://gist.github.com/rednaxelafx/843622)
“GC task thread#0 (ParallelGC)” os_prio=0 tid=0x00007fc21801f000 nid=0x8 runnable
nid 以十六进制形式给出;因此,我们在 DEC = 8,9,A, B,C,D,E,F 中将花费最多时间的线程 id 转换为 8,9,10,11,12,13,14,15 十六进制。
(请注意,这个特定的堆栈是从 Docker 容器中的 Java 中获取的,如果为 1 则使用方便的过程)让我们看看具有这个 id 的线程。
“GC task thread#0 (ParallelGC)” os_prio=0 tid=0x00007fc21801f000 nid=0x8 runnable
“GC task thread#1 (ParallelGC)” os_prio=0 tid=0x00007fc218020800 nid=0x9 runnable
“GC task thread#2 (ParallelGC)” os_prio=0 tid=0x00007fc218022800 nid=0xa runnable
“GC task thread#3 (ParallelGC)” os_prio=0 tid=0x00007fc218024000 nid=0xb runnable
“GC task thread#4 (ParallelGC)” os_prio=0 tid=0x00007fc218026000 nid=0xc runnable
“GC task thread#5 (ParallelGC)” os_prio=0 tid=0x00007fc218027800 nid=0xd runnable
“GC task thread#6 (ParallelGC)” os_prio=0 tid=0x00007fc218029800 nid=0xe runnable
“GC task thread#7 (ParallelGC)” os_prio=0 tid=0x00007fc21802b000 nid=0xf runnable
所有 GC 相关的线程;难怪它会占用大量 CPU 时间。但是GC在这里是一个问题。
使用 jstat(不是 jstack !)实用程序来快速检查 GC。
jstat -gcutil <pid>