下面是详细讲解“输出java进程的jstack信息示例分享 通过线程堆栈信息分析java线程”的完整攻略。
什么是jstack信息
jstack
是 JDK 自带的一款堆栈跟踪工具,用于查看 Java 进程中各个线程的运行状态以及占用资源情况。通过分析线程堆栈信息,可以快速定位代码中的性能问题,排查进程死锁等问题。
如何输出jstack信息
下面是输出 java 进程的 jstack 信息的步骤:
- 打开命令行窗口,输入
jps
命令找到目标 java 进程的 PID。 - 输入
jstack -l PID
命令输出目标 java 进程的 jstack 信息到控制台或文件中。
例如,jps 命令输出:
22444 java
jstack 命令输出:
jstack -l 22444 >> jstack_out.log
其中 -l
参数表示输出详细堆栈信息,>>
表示将输出追加到文件 jstack_out.log
中。
如何分析jstack信息
输出的 jstack 信息通常是一份数千行的代码调用堆栈信息,如何快速定位其中的问题所在呢?下面是几个常见的线程问题示例及解析。
示例一:死锁问题
假设输出的 jstack 信息中存在两个线程 A 和 B,它们分别持有对象锁和等待对方的对象锁,形成了死锁。
"Thread-1" #11 prio=5 os_prio=0 tid=0x00007efe152fc800 nid=0x2403 waiting on condition [0x0000700008a23000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000006d5d72c68> (a java.lang.Object)
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 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 java.lang.Thread.run(Thread.java:748)
"Thread-2" #12 prio=5 os_prio=0 tid=0x00007efe153b9800 nid=0x3803 waiting on condition [0x0000700008b26000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000006d5d72c20> (a java.lang.Object)
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 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 java.lang.Thread.run(Thread.java:748)
通过上面的代码堆栈信息,可以看到线程 A 和 B 分别处于 WAITING 状态,且都在等待同一个对象锁 <0x00000006d5d72c68>
或 <0x00000006d5d72c20>
,导致两个线程相互等待进入死锁状态。
示例二:内存泄漏问题
假设输出的 jstack 信息中存在一个线程 A,在执行完业务逻辑后,堆栈信息中有大量关于 com.example.MyClass
的引用信息。
"Thread-1" #11 prio=5 os_prio=0 tid=0x00007efe152fc800 nid=0x2403 waiting on condition [0x0000700008a23000]
java.lang.Thread.State: RUNNABLE
at com.example.MyClass.handleRequest(MyClass.java:39)
<more code>
r37c92c4@80c668d6 pool-15-thread-1] [INFO ] 2017-11-05 09:54:54 The phantom references follow:
r37c92c4@80c668d6 pool-15-thread-1] [INFO ] 2017-11-05 09:54:54 <java.lang.ref.PhantomReference@30f39991> (com.example.MyClass)
r37c92c4@80c668d6 pool-15-thread-1] [INFO ] 2017-11-05 09:54:54 <java.lang.ref.PhantomReference@183d0bb4> (com.example.MyClass)
r37c92c4@80c668d6 pool-15-thread-1] [INFO ] 2017-11-05 09:54:54 <java.lang.ref.PhantomReference@4b7f2f5f> (com.example.MyClass)
r37c92c4@80c668d6 pool-15-thread-1] [INFO ] 2017-11-05 09:54:54 Total: 3
通过上面的代码堆栈信息,可以看到线程 A 在执行完逻辑后,没有释放 com.example.MyClass
类型的资源,导致系统产生了大量的 java.lang.ref.PhantomReference
引用,导致内存泄漏。
通过分析 jstack 信息,可以发现问题所在并以此解决问题。
以上就是输出 java 进程的 jstack 信息示例分享及通过线程堆栈信息分析 java 线程的完整攻略。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:输出java进程的jstack信息示例分享 通过线程堆栈信息分析java线程 - Python技术站