One, the general query method
When we encounter a JAVA memory leak or a high number of CUPS, how do we usually fix the problem?
First let’s look at the code that starts three threads when the user enters any character: an infinite loop, a lock contention, and a deadlock. Let’s take a look at one of the changes to the CUP after startup.
1. CPU 100% code snippets
package com.netty; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * By DarkKing * Creation date: 2020/2/15 * */ Public class TestCpuThread {public static void main(String[] args) throws IOException {// Console input control BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); br.readLine(); // createBusyThread(); br.readLine(); Object o = new Object(); createLockThread(o); / / a deadlock createDeadLock (); } public static void createBusyThread() { Thread t = new Thread(new Runnable() { @Override public void run() { while (true) ; } }, "busyThreadName"); t.start(); } public static void createLockThread(final Object lock) { Thread t = new Thread(new Runnable() { @Override public void run() { synchronized(lock) { try { lock.wait(); }catch(InterruptedException e) { e.printStackTrace(); } } } },"lockThreadName"); t.start(); } public static void createDeadLock() { Object a = new Object(); Object b = new Object(); Thread t1 = new Thread(new Runnable() { @Override public void run() { synchronized (a) { try { Thread.sleep(3000); synchronized (b) { } } catch (InterruptedException e) { e.printStackTrace(); } } } },"t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { synchronized (b) { try { Thread.sleep(3000); synchronized (a) { } } catch (InterruptedException e) { e.printStackTrace(); } } } },"t2"); t1.start(); t2.start(); }}Copy the code
Before the start of
No JAVA threads are started and the CUP footprint is 0%
After the start
We found that the CPU was 100% full. Process the program started for us. At this point we must want to know what the threads are doing. Causes the CUP to consume too high! So how do you do that?
2. Troubleshooting
Get process ID
You can run the top command to view the ID of the process that consumes the most CPUS. As shown in the figure above, the process ID is 3030
View the thread IDS in the process
Once we have the process ID, we can go through
top -Hp 3030
Copy the code
Run the following command to check the thread IDS in the process. Find the thread ID3051 that consumes the most CPU.
Convert the thread ID to hexadecimal
printf "%x\n" 3051
Copy the code
The jstack command is used to check the thread execution
Use the jstack command provided by Java to export the stack information. The busyThreadName thread was found to be executing. Looking at the code, an infinite loop is found, resulting in cup100%.
jstack 3030 | grep beb
Copy the code
2. Show-busy – Threads script
However, it is a bit troublesome to execute so many commands every time we search, so we will integrate the search process into a script, isn’t it beautiful?
The following code
#! /bin/bash # @Function # Find out the highest cpu consumed threads of java, and print the stack of these threads. # $ ./show-busy-threads #ARGS= -p pid #[ $? -ne 0] PROG=`basename $0` count=3 redEcho() { [ -c /dev/stdout ] && { echo -ne "\003[1;31m" echo -n "$@" echo -e "\0ee[0m" } || echo "$@" } if ! which jstack &> /dev/null; then [ -n "$JAVA_HOME" ] && [ -f "$JAVA_HOME/bin/jstack" ] && [ -x "$JAVA_HOME/bin/jstack" ] && { export PATH="$JAVA_HOME/bin:$PATH" } || { redEcho "Error: jstack not found on PATH and JAVA_HOME!" exit 1 } fi uuid=`date +%s`_${RANDOM}_$$ cleanupWhenExit() { rm /tmp/${uuid}_* &> /dev/null } trap "cleanupWhenExit" EXIT printStackOfThread() { while read threadLine ; do pid=`echo ${threadLine} | awk '{print $1}'` threadId=`echo ${threadLine} | awk '{print $2}'` threadId0x=`printf %x ${threadId}` user=`echo ${threadLine} | awk '{print $3}'` pcpu=`echo ${threadLine} | awk '{print $5}'` jstackFile=/tmp/${uuid}_${pid} [ ! -f "${jstackFile}" ] && { jstack ${pid} > ${jstackFile} || { redEcho "Fail to jstack java process ${pid}!" rm ${jstackFile} continue } } redEcho "The stack of busy(${pcpu}%) thread(${threadId}/0x${threadId0x}) of java process(${pid}) of user(${user}):" sed "/nid=0x${threadId0x}/,/^$/p" -n ${jstackFile} done } [ -z "${pid}" ] && { ps -Leo pid,lwp,user,comm,pcpu --no-headers | awk '$4=="java"{print $0}' | sort -k5 -r -n | head --lines "${count}" | printStackOfThread } || { ps -Leo pid,lwp,user,comm,pcpu --no-headers | awk -v "pid=${pid}" '$1==pid,$4=="java"{print $0}' | sort -k5 -r -n | head --lines "${count}" | printStackOfThread }Copy the code
This command combines the ps command of the Linux operating system and the Jstack command of the JVM to locate the thread with the highest CPU usage in the Java process. This command is generally applicable to scenarios where the server load is high and you need to quickly locate the cause of the high load.
This script comes from a net friend named migratory bird tree, the original author is unknown, here retain the original author name in order to show respect for technical people, in his script on the basis of some changes.
Command format:
/show-busy-threads -p Indicates the process IDCopy the code
Example:
./show-busy-threads -p 3030
Copy the code
Example output:
Well, it will be easier to find more cpu-consuming threads in the future. In addition, everyone in the use of thread work as far as possible to name their own thread name, convenient troubleshooting.