使用 top 检查 Linux 中的 Java 线程

2022-09-01 01:55:52

我正在使用Linux中检查Java进程

top -H

但是,我无法在“COMMAND”列中读取线程的名称(因为它太长)。如果我使用“c”来扩展进程的全名,那么它仍然很长才能适应。

如何获取命令的全名?


答案 1

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

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


答案 2

这可能有点旧,但这是我所做的,有点合并顶部和jstack在一起。我使用了两个脚本,但我相信所有这些都可以在一个脚本中完成。

首先,我将带有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]*\) .*/\1/g"` > /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;

输出帮助我找出哪些线程占用了我的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
...

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


推荐