您的位置:

jstack日志分析

一、jstack日志分析概述

jstack是一个Java虚拟机自带的工具,可以生成Java线程转储文件(常称为Java堆栈转储文件),输出当前JVM内所有线程的堆栈信息。jstack日志分析在调试Java程序时非常有用,可以用于检查线程是否被锁死,线程是否在等待请求响应等问题。通过jstack日志分析,我们可以更好地定位问题,提高问题定位效率。

二、生成jstack日志

生成jstack日志的方法非常简单,只需要执行以下命令:

jstack -l pid > jstack.log

其中,pid指的是Java进程的进程ID,jstack.log是生成的日志文件名称。

三、jstack日志分析工具介绍

在进行jstack日志分析时,有很多工具可以使用,下面我们介绍几个常用的工具:

1. Eclipse MAT

Eclipse MAT是一款基于Eclipse的Java堆分析器,可以用于检查Java线程状态,分析Java堆状态等问题。MAT可以处理Java堆转储文件,jstack输出文件等等。

2. jstack解析器

jstack解析器是一款开源的Java工具,可以对jstack输出的堆栈信息进行解析和分析,支持线程状态分析、死锁分析、线程间调用分析等等。

3. VisualVM

VisualVM是一个可视化的Java性能分析工具,可以用于监控Java应用程序的性能,并且提供了线程分析功能。可以通过VisualVM生成jstack日志,并且可以对日志进行分析。

四、jstack日志分析示例

1. 线程状态分析

jstack日志中,每个线程都有自己的状态,常见的线程状态包括Runnable、Waiting、Timed_Waiting、Blocked、In_Object_Wait等等。通过分析线程的状态,我们可以看到线程是否正在执行、是否被阻塞、是否在等待某个资源。

示例代码:

"Thread-141" #1224 prio=5 os_prio=0 tid=0x00007f364804d800 nid=0x588b waiting on condition [0x00007f364ddbc000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.example.demo.service.TestService.testMethod(TestService.java:16)
        at sun.reflect.GeneratedMethodAccessor66.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)

2. 死锁分析

在jstack日志中,如果有线程被阻塞等待某个资源,而该资源又被其它线程所持有,则很可能发生死锁。通过jstack可以分析死锁线程,进一步了解死锁产生的原因,从而解决问题。

示例代码:

"Thread-1182" #1489 prio=5 os_prio=0 tid=0x00007fbf5c0e4800 nid=0x34f3 waiting for monitor entry [0x00007fbf3f3cf000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.example.demo.service.TestService.testMethod(TestService.java:26)
        - waiting to lock <0x00000007926d08d0> (a com.example.demo.entity.TestEntity)
        at sun.reflect.GeneratedMethodAccessor72.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)

"Thread-1183" #1490 prio=5 os_prio=0 tid=0x00007fbf5c0eb000 nid=0x34f4 waiting for monitor entry [0x00007fbf3f2ce000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.example.demo.service.TestService.testMethod(TestService.java:26)
        - waiting to lock <0x00000007926d0118> (a com.example.demo.entity.TestEntity)
        at sun.reflect.GeneratedMethodAccessor72.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)

3. 线程间调用分析

jstack日志可以展示线程之间的调用关系,对于分析代码调用链非常有帮助。我们可以通过jstack日志分析方法之间的调用顺序,了解程序的执行过程。

示例代码:

"Thread-1" #119 prio=5 os_prio=0 tid=0x00007ff1941d6800 nid=0x49c8 runnable [0x00007ff1986e7000]
   java.lang.Thread.State: RUNNABLE
        at com.example.demo.service.TestService.testMethod(TestService.java:16)
        at sun.reflect.GeneratedMethodAccessor66.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)

"Thread-2" #120 prio=5 os_prio=0 tid=0x00007ff1941d8800 nid=0x49c9 waiting on condition [0x00007ff1985e6000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000007926d08d0> (a com.example.demo.entity.TestEntity)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
        at com.example.demo.service.TestService.testMethod(TestService.java:24)
        at sun.reflect.GeneratedMethodAccessor71.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)

五、总结

通过本文的介绍,我们了解了jstack日志分析的流程、常用工具和分析方法。在实际的开发中,我们可以根据具体的问题选择不同的工具进行分析,可以更快地解决问题,提高开发效率。