JVM栈调优与实战

本文介绍Java栈的重要性和使用jstack工具分析线程状态的方法。通过实例演示如何定位CPU过高、死循环及死锁等问题,并提供测试代码帮助理解。

Java栈里面最重要的就是线程了。一般程序发生死循环、死锁、线程Hang住 等问题,我们都需要从栈上去分析原因。

jstack

一般出现CPU过高、线程假死等问题,都可以利用 jstack 命令来讲栈信息导出分析具体原因。 我们先来看一个案例:

  1. 启动应用
java -jar springboot-jwt-1.0.0.jar &

  1. 打印栈信息,并生成到一个app.txt文件内
jstack 10802 > app.txt
  1. 下载 app.txt 文件到本地
[lb@centos-linux ~]$ sz app.txt 

内容如下:

2021-02-01 06:05:46
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.271-b09 mixed mode):
# `#129 `内部标识号
# daemon 守护线程
# prio=9 优先级
# os_prio=0 系统级优先级
# tid=0x00007fa5a8001000 线程16进制ID
# nid=0x3943  进程16进制ID
"Attach Listener" #129 daemon prio=9 os_prio=0 tid=0x00007fa5a8001000 nid=0x3943 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"DestroyJavaVM" #128 prio=5 os_prio=0 tid=0x00007fa5d8009800 nid=0x2a33 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
# Tomcat
"http-nio-8080-Acceptor" #126 daemon prio=5 os_prio=0 tid=0x00007fa5d8bd8800 nid=0x2ad7 runnable [0x00007fa5970f1000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
	at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:424)
	at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:252)
	- locked <0x00000000f9188878> (a java.lang.Object)
	at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:469)
	at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:71)
	at org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:95)
	at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-ClientPoller" #125 daemon prio=5 os_prio=0 tid=0x00007fa5d8b42000 nid=0x2ad6 runnable [0x00007fa5971f2000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
	at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
	- locked <0x00000000f9415be8> (a sun.nio.ch.Util$3)
	- locked <0x00000000f9415bd8> (a java.util.Collections$UnmodifiableSet)
	- locked <0x00000000f9415ac0> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
	at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:709)
	at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-10" #124 daemon prio=5 os_prio=0 tid=0x00007fa5d8bc0800 nid=0x2ad5 waiting on condition [0x00007fa5972f3000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000f92c6e08> (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:107)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-9" #123 daemon prio=5 os_prio=0 tid=0x00007fa5d8ad7000 nid=0x2ad4 waiting on condition [0x00007fa5973f4000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000f92c6e08> (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:107)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-8" #122 daemon prio=5 os_prio=0 tid=0x00007fa5d8ad5000 nid=0x2ad3 waiting on condition [0x00007fa5974f5000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000f92c6e08> (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:107)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-7" #121 daemon prio=5 os_prio=0 tid=0x00007fa5d8a43000 nid=0x2ad2 waiting on condition [0x00007fa5975f6000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000f92c6e08> (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:107)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-6" #120 daemon prio=5 os_prio=0 tid=0x00007fa5d8a41000 nid=0x2ad1 waiting on condition [0x00007fa5976f7000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000f92c6e08> (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:107)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-5" #119 daemon prio=5 os_prio=0 tid=0x00007fa5d8a3f000 nid=0x2ad0 waiting on condition [0x00007fa5977f8000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000f92c6e08> (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:107)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-4" #118 daemon prio=5 os_prio=0 tid=0x00007fa5d8999000 nid=0x2acf waiting on condition [0x00007fa5978f9000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000f92c6e08> (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:107)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-3" #117 daemon prio=5 os_prio=0 tid=0x00007fa5d8997000 nid=0x2ace waiting on condition [0x00007fa5979fa000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000f92c6e08> (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:107)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-2" #116 daemon prio=5 os_prio=0 tid=0x00007fa5d8996000 nid=0x2acd waiting on condition [0x00007fa597afb000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000f92c6e08> (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:107)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-1" #115 daemon prio=5 os_prio=0 tid=0x00007fa5d84e2800 nid=0x2acc waiting on condition [0x00007fa597bfc000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000f92c6e08> (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:107)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-BlockPoller" #114 daemon prio=5 os_prio=0 tid=0x00007fa5d8af1800 nid=0x2acb runnable [0x00007fa597cfd000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
	at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
	- locked <0x00000000f918cdf8> (a sun.nio.ch.Util$3)
	- locked <0x00000000f918cd70> (a java.util.Collections$UnmodifiableSet)
	- locked <0x00000000f918c9a8> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
	at org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller.run(NioBlockingSelector.java:313)

"container-0" #113 prio=5 os_prio=0 tid=0x00007fa5d8ad0800 nid=0x2aca waiting on condition [0x00007fa597ffe000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at org.apache.catalina.core.StandardServer.await(StandardServer.java:570)
	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer$1.run(TomcatWebServer.java:197)

"Catalina-utility-2" #112 prio=1 os_prio=0 tid=0x00007fa5d8acf800 nid=0x2ac9 waiting on condition [0x00007fa5c81f0000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000ffcd9e58> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

"Catalina-utility-1" #111 prio=1 os_prio=0 tid=0x00007fa5d8cd7800 nid=0x2ac8 waiting on condition [0x00007fa5c82f1000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000ffcd9e58> (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.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007fa5d8149800 nid=0x2a3c runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007fa5d813e800 nid=0x2a3b waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007fa5d813b800 nid=0x2a3a waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007fa5d813a000 nid=0x2a39 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007fa5d8109000 nid=0x2a38 in Object.wait() [0x00007fa5c88f7000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000000e358fc40> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
	- locked <0x00000000e358fc40> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007fa5d8104800 nid=0x2a37 in Object.wait() [0x00007fa5c89f8000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000000e349aa18> (a java.lang.ref.Reference$Lock)
	at java.lang.Object.wait(Object.java:502)
	at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
	- locked <0x00000000e349aa18> (a java.lang.ref.Reference$Lock)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=0 tid=0x00007fa5d80fa800 nid=0x2a36 runnable 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007fa5d801e800 nid=0x2a34 runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007fa5d8020800 nid=0x2a35 runnable 

"VM Periodic Task Thread" os_prio=0 tid=0x00007fa5d814c800 nid=0x2a3d waiting on condition 

JNI global references: 1064

配置JVM栈大小

我们来模拟一个栈递归调用深度异常

  1. 编写测试代码
public class JvmStackRecursionDemo {

    private static int count;

    private static void counterRecursion(){
        count ++ ;
        counterRecursion();
    }

    /**
     * JVM args : -Xss1m
     */
    public static void main(String[] args) {
        try{
            counterRecursion();
        }catch (Throwable t){
            System.err.println("count="+count);
            t.printStackTrace();
        }
    }
}
  1. 指定JVM参数: -Xss10m (栈空间为10MB)
  2. 运行测试代码
count=257082
java.lang.StackOverflowError
	at com.lb.gc.JvmStackRecursionDemo.counterRecursion(JvmStackRecursionDemo.java:16)
	at com.lb.gc.JvmStackRecursionDemo.counterRecursion(JvmStackRecursionDemo.java:16)
	at com.lb.gc.JvmStackRecursionDemo.counterRecursion(JvmStackRecursionDemo.java:16)
	at com.lb.gc.JvmStackRecursionDemo.counterRecursion(JvmStackRecursionDemo.java:16)
	at com.lb.gc.JvmStackRecursionDemo.counterRecursion(JvmStackRecursionDemo.java:16)
	at com.lb.gc.JvmStackRecursionDemo.counterRecursion(JvmStackRecursionDemo.java:16)
	...

CPU过高如何处理?

基本流程:

  1. 找出10进制的线程号 top -Hp <应用进程ID>
  2. 转换为16进制 printf "%x" <线程号>
  3. jstack > <文件名> 导出栈信息,查找线程ID nid
  1. 测试代码
@RestController
public class JvmStackDeadStackDemo {

    @GetMapping("deadLoop")
    public String deadLoop()throws Exception{
        while (true){
            System.err.println("running forever");
        }
    }
}
  1. 启动 ( & 代表后台启动 )
java -jar springboot-jwt-1.0.0.jar &
  1. 执行死循环
curl locahost:8081/deadLoop
  1. 查看系统进程信息
top

可以看出 3765 这个进程CPU占用率最高

  1. 查看进程的详细信息
top -Hp 3765

可以看出 3948 这个线程占用率最高

  1. 将3948转为16进制
printf "%x" 3948

  1. 导出栈信息
# 查看进程号
[lb@centos-linux ~]$ jps -l
18482 sun.tools.jps.Jps
3765 springboot-jwt-1.0.0.jar
# 生成栈信息
[lb@centos-linux ~]$ jstack 3765 > jstac-3765.txt
[lb@centos-linux ~]$ ls
jstac-3765.txt  jstack.txt  libs  servers  soft  springboot-jwt-1.0.0.jar
  1. 查看栈信息,搜索16进制线程号关键字 f6c

nid=0xf6c ,其中0x是补位不用关注

如何排查死锁问题

关于死锁问题很简单,比如2个对象相互持有对方的锁,又想要执行下去, 就会出现死锁。 解决思路:

  1. 导出栈信息 jstack pid > jstack.txt
  2. 搜索 deadlock 关键字
  1. 编写死锁测试代码
    @GetMapping("deadLock")
    public String deadLock(){
        Object lock1 = new Object();
        Object lock2 = new Object();
        new Thread(() -> {
            // 获取自己的锁
            synchronized (lock1){
                try {
                    Thread.sleep(2000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 获取他人的锁
                synchronized (lock2){
                    System.err.println("thread1 try hold lock2");
                }
            }
        },"thread1").start();
        
        new Thread(() -> {
            // 获取自己的锁
            synchronized (lock2){
                try {
                    Thread.sleep(2000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 获取他人的锁
                synchronized (lock1){
                    System.err.println("thread2 try hold lock1");
                }
            }
        },"thread2").start();

        return "deadLock";
    }
  1. 启动应用
java -jar springboot-jwt-1.0.0.jar &
  1. 执行死锁代码
 curl localhost:8081/deadLock
 # 得到响应结果
 deadLock
  1. 导出栈信息
jstack 18899 > deadlock.txt
  1. 查找 deadlock 关键字

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值