Inspecting Java threads in Linux using top
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. How can I obtain the full name of the command?
On my machine top -H gives all the pids of the threads within a Java process, and the «COMMAND» column gives the Thread’s name.
10 Answers 10
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.
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.
I think he meant exactly what he wrote. He even used -H as parameter for «top» to tell «top» to display threads.
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.
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:
#!/bin/sh top -H -b -n 1 | grep java > /tmp/top.log jstack -l `ps fax | grep java | grep tomcat | sed "s/ *\(5*\) .*/\1/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):
#!/usr/bin/perl system("sh cpu-java.sh"); open LOG, "/tmp/top.log" or die $!; print "PID\tCPU\tMem\tJStack Info\n"; while ($l = ) < $pid = $l; $pid =~ s/root.*//g; $pid =~ s/ *//g; $hex_pid = sprintf("%#x", $pid); @values = split(/\s/, $l); $pct = $values[4]; $mem = $values[5]; open JSTACK, "/tmp/jstack.log" or die $!; while ($j = ) < 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:
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.
I haven’t used this tool much, but it seems to cover my answer and some more: github.com/aragozin/jvm-tools
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:
Sample output (showing ant and IntelliJ running):
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.
NOTE: jtop is written in Python and requires that jstack be installed.
As far as I found out jstack is outdated as of JDK 8. What I used to retrieve all Java Thread names is:
If the well-known tmp file .java_pidnnnn already exists for this java process, then you need to run jcmd with the user executing the java process, and it maybe better anyway if the process needs access to this file also.
With OpenJDK on Linux, JavaThread names don’t propagate to native threads, you cannot see java thread name while inspecting native threads with any tool.
However there is some work in progress:
Personally, I find the OpenJDK development tool slow so I just apply patches myself.
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).
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.
Name: jstack-top.sh
#!/bin/sh # # jstack-top - join jstack and top to show cpu usage, etc. # # Usage: jstack-top | view - # USER=$1 TOPS="/tmp/jstack-top-1.log" JSKS="/tmp/jstack-top-2.log" PIDS="$(ps -u $ --no-headers -o pid:1,cmd:1 | grep 'bin/java' | grep -v 'grep' | cut -d' ' -f1)" if [ -f $ ]; then rm $ fi for PID in $; do jstack -l $ | grep "nid=" >>$ done top -u $ -H -b -n 1 | grep "%CPU\|java" | sed -e 's/[[:space:]]*$//' > $ while IFS= read -r TOP; do NID=$(echo "$" | sed -e 's/^[[:space:]]*//' | cut -d' ' -f1) if [ "$" = "PID" ]; then JSK="" TOP="$ JSTACK" else NID=$(printf 'nid=0x%x' $) JSK=$(grep "$ " $) fi echo "$ $" done < "$"
Expanding on Andre's earlier answer in Perl, here is one in Python that runs significantly faster.
It re-uses files created earlier and does not loop several times over the jstack output:
#!/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*(1*)(\s+[^\s]*)\s+(3+)') # 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, "") # Grab CPU percent pct = int(m.group(3)) # Emit line print "%d\t%s\t%d\t%s" % (pid, nid, pct, tname)
Show Threads Using PS Command in Linux
In the modern operating systems, threads serve as a popular programming abstraction. These threads share resources like open files, space, and memory addresses when this happens. It avoids the inter-process communication (expensive IPC) channels and reduces forking overhead. As a result, threads perform a concurrent execution mechanism.
In Linux, threads are also known as LWP or Lightweight Processes. These threads created within the program have a “thread group ID”, the same as the program’s PID. There is an individual thread ID (TID) assigned to each thread. Scheduler threads in the Linux kernel share a few resources, which are standard processes.
Besides displaying the process-level information by default, classic command-line tools, such as top and ps, can display the thread-level information as well. Ps, top, and htop are classic commands that show you the process-level information by default. You can also view the thread-level information using the previous commands. This guide will only go through the ps command and explain how the ps command shows threads in Linux.
Show Threads Using PS Command in Linux
With the help of the ps command, you can view the threads with many filters like PID (Process ID), application name, etc. This command does not work on BSD or macOS, as there is no option to show that the thread and the -t parameter have a different meaning.
Let’s start with the following command in the terminal to list all the threads using the ps command:
Show Threads with PID
Here is the standard syntax of ps commands to view the threads using PIDs:
You can view the threads for specific PIDs. Follow the previous standard syntax and put the PID number which you want to know the threads.
For example, we use the PID . The syntax is as follows:
The “SPID” column shows the thread IDs in the previous output. And the “CMD” column represents the thread names.
Show Threads with Application Name
Here is the standard syntax of the ps command to view the threads using the application name:
Option | Description |
---|---|
-T | List all threads |
-C | Specifies the application name |
For example, let’s find out the thread related to the Bash application. Here is the basic command:
Show Threads with Filter
The standard syntax of the ps command is to view the threads using the filter as follows:
Option | Description |
---|---|
-T | List all threads |
-e | Shows all processes |
| | Pipes the output to the next command |
grep | It filters the content with the help of |
You can filter the content through the application name. Type and execute the following command to accomplish it:
You can also filter the threads using their PIDs:
In the previous output, you may notice that all the threads have the same PID. It means that all the previous threads are in the same process.
To find the sum of all the running threads in the system, you can execute the following command:
You can use the “pgrep” or “pidof” to get the process name’s process id:
How to get the detail information of one Linux thread
I already know that ps -ef and top will list the thread information. In fact, I got a pid via top. I would like to check more detail information about this thread, I remember there should be a Linux command to do so. Thank you @Shahbaz That's answer my question. However I still would like to make it clear. What I want is: I have a pid, I would like to know more information about this thread like where is the thread start such as which folder? and maybe memory related. The answer I am waiting actually
pmap pid $pmap 498 498: ./bin/redis-server redis.conf 0000000000400000 224K r-x-- /var/www/bin/redis-2.2.11/bin/redis-server 0000000000637000 12K rwx-- /var/www/bin/redis-2.2.11/bin/redis-server 000000000063a000 80K rwx-- [ anon ] 0000000011204000 57756K rwx-- [ anon ] 0000003dd7a00000 112K r-x-- /lib64/ld-2.5.so 0000003dd7c1b000 4K r-x-- /lib64/ld-2.5.so 0000003dd7c1c000 4K rwx-- /lib64/ld-2.5.so 0000003dd7e00000 1332K r-x-- /lib64/libc-2.5.so 0000003dd7f4d000 2048K ----- /lib64/libc-2.5.so 0000003dd814d000 16K r-x-- /lib64/libc-2.5.so 0000003dd8151000 4K rwx-- /lib64/libc-2.5.so 0000003dd8152000 20K rwx-- [ anon ] 0000003dd8200000 520K r-x-- /lib64/libm-2.5.so 0000003dd8282000 2044K ----- /lib64/libm-2.5.so 0000003dd8481000 4K r-x-- /lib64/libm-2.5.so 0000003dd8482000 4K rwx-- /lib64/libm-2.5.so 0000003dd8a00000 88K r-x-- /lib64/libpthread-2.5.so 0000003dd8a16000 2044K ----- /lib64/libpthread-2.5.so 0000003dd8c15000 4K r-x-- /lib64/libpthread-2.5.so 0000003dd8c16000 4K rwx-- /lib64/libpthread-2.5.so 0000003dd8c17000 16K rwx-- [ anon ] 00002b000ff11000 4K rwx-- [ anon ] 00002b000ff28000 416K rwx-- [ anon ] 00002b000ff91000 480K rwx-- [ anon ] 00002b0010fba000 1536K rwx-- [ anon ] 00007fff90700000 84K rw--- [ stack ] ffffffffff600000 8192K ----- [ anon ] total 77052k