java堆栈跟踪工具jstack的使用教程
作者:242030
1、jstack介绍
jstack(stack trace for java)是java虚拟机自带的一种堆栈跟踪工具。
jstack主要用于生成java虚拟机当前时刻的线程快照,线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。
线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。
jstack主要分为两个功能:
- 针对活着的进程做本地的或远程的线程dump
- 针对core文件做线程dump
当指定的进程在64位Java虚拟机上运行时,可能需要指定-J-d64选项,例如:jstack -J-d64 -m pid。
2、线程状态
线程通常有下面5中状态:
1、新建状态(New): 新创建了一个线程对象。
2、就绪状态(Runnable) :线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running): 就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。
当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
关于线程状态,具体也可以查看:java.lang.Thread.State类。
想要通过jstack命令来分析线程的情况的话,首先要知道线程都有哪些状态,下面这些状态是我们使用jstack命
令查看线程堆栈信息时可能会看到的线程的几种状态:
- RUNNABLE,线程运行中或I/O等待
- BLOCKED,线程被阻塞,在等待monitor锁(synchronized关键字)
- TIMED_WAITING ,线程在等待唤醒,但设置了时限
- WAITING ,线程在无限等待唤醒
在线程的堆栈中,需要特别留意以下几种状态:
- Deadlock: 死锁(重点关注)
- Waiting on condition: 等待资源(重点关注)
- Waiting on monitor entry : 等待获取监视器(重点关注)
- Blocked :阻塞(重点关注)
- Runnable :执行中
- Suspended : 暂停
- Object.wait()或TIME_WAITING :对象等待中
- Parked : 停止
3、jstack命令格式
jstack [ option ] pid
jstack [ option ] executable core
jstack [ option ] [server-id@]remote-hostname-or-IP
pid:Java进程的ID,可以通过jps命令查询到。
executable: 产生core dump的Java可执行程序。
core:要打印的堆栈跟踪的核心文件。
server-id:当多个DEBUG服务器在同一远程主机上运行时,可使用的可选唯一ID。
remote-hostname-or-IP:远程DEBUG的服务器主机名或IP地址。
pid: 需要被打印配置信息的java进程id,可以用jps查询。
常用参数说明:
-F:当 jstack [-l] pid 没有响应时,强制打印一个堆栈转储。
-l:打印关于锁的其他信息,比如拥有的java.util.concurrent ownable同步器的列表,会使得JVM停顿得长久得多。
-m:打印包含Java和本机C/ C++帧的混合模式堆栈跟踪。
-h:打印帮助信息。
-help:打印帮助信息。
3.1 jstack pid
第一行各个单词的解析,
daemon:线程名称 。
prio:线程优先级
tid:指Java Thread id。
nid:指native线程的id。。
[0x000000002369e000]:线程栈起始地址。
3.2 死循环
package com.example.controller; public class Test2 { public static void main(String[] args) { while (true) { } } }
3.3 Object.wait()情况
package com.example.controller; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test3 { static class TestTask implements Runnable { @Override public void run() { synchronized (this) { try { //等待被唤醒 wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { ExecutorService ex = Executors.newFixedThreadPool(1); ex.execute(new TestTask()); } }
3.4 死锁情况
package com.example.controller; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test4 { public static void main(String[] args) { Object obj1 = new Object(); Object obj2 = new Object(); ExecutorService ex = Executors.newFixedThreadPool(2); // 起10个线程 for (int i = 0; i < 10; i++) { int order = i % 2 == 0 ? 1 : 0; ex.execute(new TestTask(order, obj1, obj2)); } } static class TestTask implements Runnable { private Object obj1; private Object obj2; private int order; public TestTask(int order, Object obj1, Object obj2) { this.order = order; this.obj1 = obj1; this.obj2 = obj2; } public void test1() throws InterruptedException { synchronized (obj1) { synchronized (obj2) { System.out.println("test。。。"); } } } public void test2() throws InterruptedException { synchronized (obj2) { synchronized (obj1) { System.out.println("test。。。"); } } } @Override public void run() { while (true) { try { if (this.order == 1) { this.test1(); } else { this.test2(); } } catch (InterruptedException e) { e.printStackTrace(); } } } } }
3.5 等待io
package com.example.controller; import java.io.IOException; import java.io.InputStream; public class Test5 { public static void main(String[] args) throws IOException { InputStream is = System.in; int i = is.read(); System.out.println("exit。"); } }
以上就是java堆栈跟踪工具jstack的使用教程的详细内容,更多关于java jstack的资料请关注脚本之家其它相关文章!