使用 top 检查 Linux 中的 Java 线程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4764167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Inspecting Java threads in Linux using top
提问by Jake
I am inspecting a Java process in Linux using
我正在使用 Linux 检查 Java 进程
top -H
However, I cannot read the name of the thread in the "COMMAND" column (because it is too long). If I use 'c' to expand the full name of the process, then it is still to long to fit.
但是,我无法在“COMMAND”列中读取线程的名称(因为它太长)。如果我使用“c”来扩展进程的全名,那么它仍然太长而无法适应。
How can I obtain the full name of the command?
如何获取命令的全名?
回答by Hendrik Brummermann
You can inspect java threads with the tool jstack
. It will list the names, stacktraces and other useful information of all threads belonging to the specified process pid.
您可以使用该工具检查 Java 线程jstack
。它将列出属于指定进程 pid 的所有线程的名称、堆栈跟踪和其他有用信息。
Edit: The parameter nid in the thread dump of jstack is the hex version of the LWP that is displayed by top in the pid column for threads.
编辑:jstack 的线程转储中的参数 nid 是在线程的 pid 列中由 top 显示的 LWP 的十六进制版本。
回答by Wyzard
Threads don't have names as far as the kernel is concerned; they only have ID numbers. The JVM assigns names to threads, but that's private internal data within the process, which the "top" program can't access (and doesn't know about anyway).
就内核而言,线程没有名称;他们只有身份证号码。JVM 为线程分配名称,但这是进程内的私有内部数据,“顶级”程序无法访问(无论如何也不知道)。
回答by Andre
This might be a little old, but here's what I did to kinda merge top and jstack together. I used two scripts, but I'm sure it all could be done in one.
这可能有点旧,但这是我将 top 和 jstack 合并在一起的方法。我使用了两个脚本,但我相信这一切都可以在一个脚本中完成。
First, I save the output of top with the pids for my java threads into a file and save the jstack output into another file:
首先,我将带有 java 线程的 pid 的 top 输出保存到一个文件中,并将 jstack 输出保存到另一个文件中:
#!/bin/sh
top -H -b -n 1 | grep java > /tmp/top.log
jstack -l `ps fax | grep java | grep tomcat | sed "s/ *\([0-9]*\) .*//g"` > /tmp/jstack.log
Then I use a perl script to call the bash script (called cpu-java.sh here) and kinda merge the two files (/tmp/top.log and /tmp/jstack.log):
然后我使用 perl 脚本调用 bash 脚本(这里称为 cpu-java.sh)并合并两个文件(/tmp/top.log 和 /tmp/jstack.log):
#!/usr/bin/perl
system("sh cpu-java.sh");
open LOG, "/tmp/top.log" or die $!;
print "PID\tCPU\tMem\tJStack Info\n";
while ($l = <LOG>) {
$pid = $l;
$pid =~ s/root.*//g;
$pid =~ s/ *//g;
$hex_pid = sprintf("%#x", $pid);
@values = split(/\s{2,}/, $l);
$pct = $values[4];
$mem = $values[5];
open JSTACK, "/tmp/jstack.log" or die $!;
while ($j = <JSTACK>){
if ($j =~ /.*nid=.*/){
if ($j =~ /.*$hex_pid.*/){
$j =~ s/\n//;
$pid =~ s/\n//;
print $pid . "\t" . $pct . "\t" . $mem . "\t" . $j . "\n";
}
}
}
close JSTACK;
}
close LOG;
The output helps me to find out which threads are hogging my cpu:
输出帮助我找出哪些线程占用了我的 CPU:
PID CPU Mem JStack Info
22460 0 8.0 "main" prio=10 tid=0x083cb800 nid=0x57bc runnable [0xb6acc000]
22461 0 8.0 "GC task thread#0 (ParallelGC)" prio=10 tid=0x083d2c00 nid=0x57bd runnable
22462 0 8.0 "GC task thread#1 (ParallelGC)" prio=10 tid=0x083d4000 nid=0x57be runnable
22463 0 8.0 "GC task thread#2 (ParallelGC)" prio=10 tid=0x083d5800 nid=0x57bf runnable
22464 0 8.0 "GC task thread#3 (ParallelGC)" prio=10 tid=0x083d7000 nid=0x57c0 runnable
...
Then I can go back to /tmp/jstack.log and take a look at the stack trace for the problematic thread and try to figure out what's going on from there. Of course this solution is platform-dependent, but it should work with most flavors of *nix and some tweaking here and there.
然后我可以返回到 /tmp/jstack.log 并查看有问题的线程的堆栈跟踪,并尝试从那里找出发生了什么。当然,这个解决方案是依赖于平台的,但它应该适用于大多数 *nix 风格,并在这里和那里进行一些调整。
回答by Josh Guilfoyle
I have created a top-like command specifically for visualizing Java threads ordered by CPU usage and posted the source code at: https://github.com/jasta/jprocps. The command-line syntax is not nearly as rich as top, but it does support some of the same commands:
我创建了一个类似 top 的命令,专门用于可视化按 CPU 使用率排序的 Java 线程,并将源代码发布在:https: //github.com/jasta/jprocps。命令行语法不如 top 丰富,但它确实支持一些相同的命令:
$ jtop -n 1
Sample output (showing ant and IntelliJ running):
示例输出(显示 ant 和 IntelliJ 正在运行):
PID TID USER %CPU %MEM THREAD
13480 13483 jasta 104 2.3 main
13480 13497 jasta 86.3 2.3 C2 CompilerThread1
13480 13496 jasta 83.0 2.3 C2 CompilerThread0
4866 4953 jasta 1.0 13.4 AWT-EventQueue-1 12.1.4#IC-129.713, eap:false
4866 14154 jasta 0.9 13.4 ApplicationImpl pooled thread 36
4866 5219 jasta 0.8 13.4 JobScheduler pool 5/8
From this output, I can pull up the thread's stack trace in jconsole
or jstack
manually and figure out what's going on.
从这个输出中,我可以提取jconsole
或jstack
手动提取线程的堆栈跟踪并找出发生了什么。
NOTE:jtop
is written in Python and requires that jstack
be installed.
注意:jtop
是用 Python 编写的,需要jstack
安装。
回答by milan
With OpenJDK on Linux, JavaThreadnames don't propagate to native threads, you cannot see java thread name while inspecting native threads with any tool.
使用 Linux 上的 OpenJDK,JavaThread名称不会传播到本机线程,使用任何工具检查本机线程时都看不到 java 线程名称。
However there is some work in progress:
但是,还有一些工作正在进行中:
- https://bugs.openjdk.java.net/browse/JDK-7102541
- http://mail.openjdk.java.net/pipermail/hotspot-dev/2012-July/006211.html
- https://bugs.openjdk.java.net/browse/JDK-7102541
- http://mail.openjdk.java.net/pipermail/hotspot-dev/2012-July/006211.html
Personally, I find the OpenJDK development tool slow so I just apply patches myself.
就我个人而言,我发现 OpenJDK 开发工具很慢,所以我自己打补丁。
回答by Scheintod
Old question, but I had just the same problem with top
.
老问题,但我对top
.
It turns out, you can scrolltop's output to the right simply by using the cursors keys :)
事实证明,您只需使用光标键即可将 top 的输出滚动到右侧:)
(but unfortunately there won't be any thread nameshown)
(但不幸的是不会显示任何线程名称)
回答by Trinimon
As far as I found out jstack is outdatedas of JDK 8. What I used to retrieve all Java Thread names is:
据我发现jstack自 JDK 8 起已过时。我用来检索所有 Java 线程名称的是:
<JDK_HOME>/bin/jcmd <PID> Thread.print
Check jcmd documentationfor more.
查看jcmd 文档了解更多信息。
回答by Rick O'Sullivan
This shell script combines the output from jstack and top to list Java threads by CPU usage. It expects one argument, the account user that owns the processes.
这个 shell 脚本将 jstack 和 top 的输出结合起来,按 CPU 使用率列出 Java 线程。它需要一个参数,即拥有进程的帐户用户。
Name:jstack-top.sh
名称:jstack-top.sh
#!/bin/sh
#
# jstack-top - join jstack and top to show cpu usage, etc.
#
# Usage: jstack-top <user> | view -
#
USER=
TOPS="/tmp/jstack-top-1.log"
JSKS="/tmp/jstack-top-2.log"
PIDS="$(ps -u ${USER} --no-headers -o pid:1,cmd:1 | grep 'bin/java' | grep -v 'grep' | cut -d' ' -f1)"
if [ -f ${JSKS} ]; then
rm ${JSKS}
fi
for PID in ${PIDS}; do
jstack -l ${PID} | grep "nid=" >>${JSKS}
done
top -u ${USER} -H -b -n 1 | grep "%CPU\|java" | sed -e 's/[[:space:]]*$//' > ${TOPS}
while IFS= read -r TOP; do
NID=$(echo "${TOP}" | sed -e 's/^[[:space:]]*//' | cut -d' ' -f1)
if [ "${NID}" = "PID" ]; then
JSK=""
TOP="${TOP} JSTACK"
else
NID=$(printf 'nid=0x%x' ${NID})
JSK=$(grep "${NID} " ${JSKS})
fi
echo "${TOP} ${JSK}"
done < "${TOPS}"
回答by reichhart
You mentioned "Linux". Then using the little tool "threadcpu" might be a solution:
你提到了“Linux”。然后使用小工具“threadcpu”可能是一个解决方案:
threadcpu_-_show_cpu_usage_of_threads
threadcpu_-_show_cpu_usage_of_threads
$ threadcpu -h
threadcpu shows CPU usage of threads in user% and system%
usage:
threadcpu [-h] [-s seconds] [-p path-to-jstack]
options:
-h display this help page
-s measuring interval in seconds, default: 10
-p path to JRE jstack, default: /usr/bin/jstack
example usage:
threadcpu -s 30 -p /opt/java/bin/jstack 2>/dev/null|sort -n|tail -n 12
output columns:
user percent <SPACE> system percent <SPACE> PID/NID [ <SPACE> JVM thread name OR (process name) ]
Some sample outputs:
一些示例输出:
$ threadcpu |sort -n|tail -n 8
3 0 33113 (klzagent)
3 0 38518 (klzagent)
3 0 9874 (BESClient)
3 41 6809 (threadcpu)
3 8 27353 VM Periodic Task Thread
6 0 31913 hybrisHTTP4
21 8 27347 C2 CompilerThread0
50 41 3244 (BESClient)
$ threadcpu |sort -n|tail -n 8
0 20 52358 (threadcpu)
0 40 32 (kswapd0)
2 50 2863 (BESClient)
11 0 31861 Gang worker#0 (Parallel CMS Threads)
11 0 31862 Gang worker#1 (Parallel CMS Threads)
11 0 31863 Gang worker#2 (Parallel CMS Threads)
11 0 31864 Gang worker#3 (Parallel CMS Threads)
47 10 31865 Concurrent Mark-Sweep GC Thread
$ threadcpu |sort -n|tail -n 8
2 0 14311 hybrisHTTP33
2 4 60077 ajp-bio-8009-exec-11609
2 8 30657 (klzagent)
4 0 5661 ajp-bio-8009-exec-11649
11 16 28144 (batchman)
15 20 3485 (BESClient)
21 0 7652 ajp-bio-8009-exec-11655
25 0 7611 ajp-bio-8009-exec-11654
The output is intentionally very simple to make further processing (e.g. for monitoring) more easy.
输出故意非常简单,以便更容易地进行进一步处理(例如,用于监控)。
回答by Martin Schroeder
Expanding on Andre'searlier answer in Perl, here is one in Python that runs significantly faster.
扩展安德烈早先在 Perl 中的答案,这里是 Python 中运行速度明显更快的答案。
It re-uses files created earlier and does not loop several times over the jstack output:
它重用之前创建的文件,并且不会在 jstack 输出上循环多次:
#!/usr/bin/env python
import re
import sys
import os.path
import subprocess
# Check if jstack.log top.log files are present
if not os.path.exists("jstack.log") or not os.path.exists("top.log"):
# Delete either file
os.remove("jstack.log") if os.path.exists("jstack.log") else None
os.remove("top.log") if os.path.exists("top.log") else None
# And dump them via a bash run
cmd = """
pid=$(ps -e | grep java | sed 's/^[ ]*//g' | cut -d ' ' -f 1)
top -H -b -n 1 | grep java > top.log
/usr/intel/pkgs/java/1.8.0.141/bin/jstack -l $pid > jstack.log
"""
subprocess.call(["bash", "-c", cmd])
# Verify that both files were written
for f in ["jstack.log", "top.log"]:
if not os.path.exists(f):
print "ERROR: Failed to create file %s" % f
sys.exit(1)
# Thread ID parser
jsReg = re.compile('"([^\"]*)".*nid=(0x[0-9a-f]*)')
# Top line parser
topReg = re.compile('^\s*([0-9]*)(\s+[^\s]*){7}\s+([0-9]+)')
# Scan the entire jstack file for matches and put them into a dict
nids = {}
with open("jstack.log", "r") as jstack:
matches = (jsReg.search(l) for l in jstack if "nid=0x" in l)
for m in matches:
nids[m.group(2)] = m.group(1)
# Print header
print "PID\tNID\tCPU\tTHREAD"
# Scan the top output and emit the matches
with open("top.log", "r") as top:
matches = (topReg.search(l) for l in top)
for m in matches:
# Grab the pid, convert to hex and fetch from NIDS
pid = int(m.group(1))
nid = "0x%x" % pid
tname = nids.get(nid, "<MISSING THREAD>")
# Grab CPU percent
pct = int(m.group(3))
# Emit line
print "%d\t%s\t%d\t%s" % (pid, nid, pct, tname)