一、什麼是jstack-l
jstack-l是一種Java HotSpot VM的命令行工具,用於生成Java堆棧信息的文本文件。這對於分析Java應用程序的內存問題非常有用,因為它可以向我們展示Java堆中正在運行的線程的狀態,並告訴我們線程正在執行的代碼行。
可以使用此工具檢測線程死鎖,並可發現一些問題,如線程阻塞、內存泄漏等。同時,對於高並發應用程序,它也非常有用,因為它可以幫助我們查找並解決性能問題。
二、jstack-l的使用方法
可以使用以下命令來生成jstack-l的輸出:
jstack -l <PID> > <filename.txt>
這將生成一個名為“filename.txt”的文本文件,其中包含Java Heap中正在運行的線程信息。在大多數情況下,您需要手動運行此命令,並將輸出發送到支持人員以進行分析。
例如,在Linux機器上,我們可以運行以下命令來生成jstack-l的輸出文件:
jstack -l 1000 > /tmp/jstack.txt
這將生成一個名為“jstack.txt”的文本文件,在/tmp目錄下。
三、如何分析jstack-l的輸出
1. 查看線程狀態
jstack-l的輸出會為我們提供Java Heap中正在運行的線程信息。從輸出中,我們可以查看每個線程的狀態,如RUNNABLE、WAITING、TIMED_WAITING等。
"http-nio-8080-AsyncTimeout" #30 daemon prio=5 os_prio=0 tid=0x00007f038c004000 nid=0x5a1 waiting on condition [0x00007f037cff8000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.apache.catalina.core.AsyncTimeout$AsyncTimeoutTimer.run(AsyncTimeout.java:295)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
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)
該線程的狀態為“TIMED_WAITING”,即它正在等待一段時間後再次運行。這是由線程調度器控制的等待類型。
2. 查看線程棧信息
jstack-l的輸出還將為我們提供有關線程堆棧的詳細信息。從輸出中,我們可以查看每個線程正在執行的代碼行。
"http-nio-8080-AsyncTimeout" #30 daemon prio=5 os_prio=0 tid=0x00007f038c004000 nid=0x5a1 waiting on condition [0x00007f037cff8000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.apache.catalina.core.AsyncTimeout$AsyncTimeoutTimer.run(AsyncTimeout.java:295)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
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)
該線程正在執行的代碼行是“java.lang.Thread.sleep(Native Method)”和“org.apache.catalina.core.AsyncTimeout$AsyncTimeoutTimer.run(AsyncTimeout.java:295)”。
3. 查看線程鎖
jstack-l的輸出還將為我們提供有關每個線程正在鎖定的對象的詳細信息。從輸出中,我們可以查看每個對象以及該對象正在被哪個線程鎖定。
java.lang.Thread.State: BLOCKED (on object monitor)
at com.example.app.MyRunnable.run(MyRunnable.java:16)
- locked <0x000000076ad20fd8> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
該線程正在等待一個鎖對象,該鎖對象被另一個線程鎖定,並且該信息還告訴了我們鎖定該對象的線程:
- locked <0x000000076ad20fd8> (a java.lang.Object)
4. 查看CPU使用情況
jstack-l的輸出還將為我們提供有關Java虛擬機正在使用的CPU情況的詳細信息。從輸出中,我們可以查看當前Java線程正在使用的CPU時間,以便我們了解哪些線程使用了最多的CPU。
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 <0x0000000711975b10> (a io.netty.channel.nio.SelectedSelectionKeySet)
- locked <0x0000000580aabed8> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000007119371b0> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:748)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)
at java.lang.Thread.run(Thread.java:745)
此信息告訴我們該線程正在運行,並且正在使用CPU時間。
四、結論
jstack-l是一個非常有用的工具,它可以幫助我們分析Java應用程序的內存問題和線程問題。通過使用jstack-l,我們可以查看Java堆中正在運行的線程狀態、線程棧信息、線程鎖狀態和CPU使用情況。這對於解決Java應用程序中的問題非常有幫助。
原創文章,作者:SCAS,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/143400.html