使用top检查Linux中的Java线程

Jak*_*ake 36 java linux top-command

我在使用Linux检查Java进程

top -H
Run Code Online (Sandbox Code Playgroud)

但是,我无法读取"COMMAND"列中的线程名称(因为它太长).如果我使用'c'来扩展进程的全名,那么它仍然很长.

如何获取命令的全名?

Hen*_*ann 27

您可以使用该工具检查Java线程jstack.它将列出属于指定进程pid的所有线程的名称,堆栈跟踪和其他有用信息.

编辑:jstack的线程转储中的参数nid是LWP的十六进制版本,它由顶部显示在线程的pid列中.

  • 我认为他的意思正是他写的.他甚至使用-H作为"top"的参数来告诉"top"显示线程. (2认同)

And*_*dre 25

这可能有点旧,但这就是我所做的有点合并top和jstack在一起.我使用了两个脚本,但我确信这一切都可以在一个脚本中完成.

首先,我将带有我的java线程的pids的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]*\) .*/\1/g"` > /tmp/jstack.log
Run Code Online (Sandbox Code Playgroud)

然后我使用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;
Run Code Online (Sandbox Code Playgroud)

输出帮助我找出哪些线程占用我的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
...
Run Code Online (Sandbox Code Playgroud)

然后我可以回到/tmp/jstack.log并查看有问题的线程的堆栈跟踪,并尝试弄清楚从那里发生了什么.当然这个解决方案依赖于平台,但是它应该适用于*nix的大多数版本以及一些调整.


小智 14

我创建了一个类似顶级的命令,专门用于可视化按CPU使用顺序排列的Java线程,并将源代码发布在:https://github.com/jasta/jprocps.命令行语法并不像top那样丰富,但它确实支持一些相同的命令:

$ jtop -n 1
Run Code Online (Sandbox Code Playgroud)

示例输出(显示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
Run Code Online (Sandbox Code Playgroud)

从这个输出,我可以拉出线程的堆栈跟踪jconsolejstack手动,并找出正在发生的事情.

注意: jtop是用Python编写的,需要jstack安装.


Tri*_*mon 5

据我发现jstack自 JDK 8 起已过时。我用来检索所有 Java 线程名称的是:

<JDK_HOME>/bin/jcmd <PID> Thread.print
Run Code Online (Sandbox Code Playgroud)

查看jcmd 文档了解更多信息。