一、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 (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 (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 (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日誌分析的流程、常用工具和分析方法。在實際的開發中,我們可以根據具體的問題選擇不同的工具進行分析,可以更快地解決問題,提高開發效率。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/244826.html