jstack analysis of JVM problems

Keywords: Programming Java Tomcat Apache snapshot

Background:

jstack is used to generate a thread snapshot of the current time of the JVM. It can locate problems such as thread deadlock, dead cycle, thread pause caused by too long external request time.

Thread classification:

gc thread

Tomcat worker thread

Tomcat Boss thread (IO thread)

Dubbo

Netty

JIT thread [CompilerThread3]

User defined thread pool

Thread status:

WAITING

TIMED_WAITING

BLOCK

RUNNABLE

TERMANTED

Actual operation:

Usage 1: find threads with high CPU consumption (dead cycle)

1. Top - HP process ID to view the status of all threads in the process;

2. printf "%x\n" thread ID converts the thread ID with high CPU consumption to hexadecimal;

3. jstack -l process ID > log.txt;

Find the thread ID obtained in step 2 in log.txt and view the call stack.

"http-nio2-9386-exec-25" #52 daemon prio=5 os_prio=31 tid=0x00007ff9c46d6800 nid=0x7c03 waiting on condition [0x000070000a651000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000007816cdbc8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
        at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

Usage 2: find deadlock

    private Object lock1 = new Object();
    private Object lock2 = new Object();

    @RequestMapping("/deadlock")
    public String deadlock(){
        Thread thread1 = new Thread(){
            @Override
            public void run() {
                super.run();
                synchronized (lock1){
                    LockSupport.parkNanos(1000000);
                    synchronized (lock2){

                    }
                }
            }
        };
        thread1.setName("yzy");
        thread1.start();

        Thread thread2 = new Thread(){
            @Override
            public void run() {
                super.run();
                synchronized (lock2){
                    LockSupport.parkNanos(1000000);
                    synchronized (lock1){

                    }
                }
            }
        };
        thread2.setName("yzk");
        thread2.start();

        return "OK";
    }

 

Found one Java-level deadlock:
=============================
"yzk":
  waiting to lock monitor 0x00007ff9c1803618 (object 0x0000000781c4e118, a java.lang.Object),
  which is held by "yzk"
"yzk":
  waiting to lock monitor 0x00007ff9c18036c8 (object 0x0000000781c4e108, a java.lang.Object),
  which is held by "yzy"
"yzy":
  waiting to lock monitor 0x00007ff9c1803618 (object 0x0000000781c4e118, a java.lang.Object),
  which is held by "yzk"

Java stack information for the threads listed above:
===================================================
"yzk":
        at com.kuaikan.data.horadric.backend.controller.PingController$2.run(PingController.java:48)
        - waiting to lock <0x0000000781c4e118> (a java.lang.Object)
"yzk":
        at com.kuaikan.data.horadric.backend.controller.PingController$2.run(PingController.java:51)
        - waiting to lock <0x0000000781c4e108> (a java.lang.Object)
        - locked <0x0000000781c4e118> (a java.lang.Object)
"yzy":
        at com.kuaikan.data.horadric.backend.controller.PingController$1.run(PingController.java:36)
        - waiting to lock <0x0000000781c4e118> (a java.lang.Object)
        - locked <0x0000000781c4e108> (a java.lang.Object)

Best practices:

Both Thread and ThreadPool need to define a name

 

 

 

 

in addition to:

jstat -gc,jmap -dump:live,format=b,file=dump.hprof Some tools such as [pid] are used to analyze GC and memory leak, expecting to decompose next time.

Posted by PrinceOfDragons on Wed, 30 Oct 2019 22:13:15 -0700