jstack命令
语法格式
jstack [ option ] pid
jstack [ option ] executable core
jstack [ option ] [server-id@]remote-hostname-or-IP
options
命令行选项。
executable
生成核心转储的Java可执行文件。
core
要为其打印堆栈跟踪的核心文件。
server-id
如果多个调试服务器在同一远程主机上运行,则为可选唯一ID。
remote-hostname-or-IP
远程调试服务器主机名或IP地址。
认识jstack
options (摘要)
- -m:打印混合模式(Java和本机C / C ++帧)堆栈跟踪。
jps 命令获取pid:
jstack 命令(这里只截取了部分图片)
线程状态
jstack是java虚拟机自带的一种堆栈跟踪工具,所以 jstack 命令主要用来查看Java线程的调用堆栈的,可以用来分析线程问题(如死锁)。当我们使用 jstack 命令查看线程堆栈信息时可能会看到这几种状态:
- NEW:未启动的。不会出现在Dump中
- RUNNABLE:在虚拟机内执行的
- BLOCKED:受阻塞并等待监视器锁
- WATING:无限期等待另一个线程执行特定操作
- TIMED_WATING:有时限的等待另一个线程的特定操作
- TERMINATED:已退出的
Moitor
Monitor 是 Java中用以实现线程之间的互斥与协作的主要手段 ,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。下 面这个图,描述了线程和 Monitor之间关系,以 及线程的状态转换图:
进入区(Entrt Set) :表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则迚入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。
拥有者(The Owner) :表示某一线程成功竞争到对象锁。
等待区(Wait Set) :表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒 。
一个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread” , 而其它线程都是 “Waiting Thread” , 分别在两个队列 “ Entry Set” 和 “Wait Set” 里面等候 。 在 “Entry Set” 中等待的线程状态是 “Waiting for monitor entry” , 而在 “Wait Set” 中等待的线程状态是 “in Object.wait()” 。 先看 “Entry Set”里面的线程。我们称被 synchronized保护起来的代码段为临界区。当一个线程申请进入临界区时,它就进入了 “Entry Set”队列。对应的 code就像 :
调用修饰
表示线程在方法调用时,额外的重要的操作。线程Dump分析的重要信息。修饰上方的方法调用:
- locked <地址> 目标:使用synchronized申请对象锁成功,监视器的拥有者。
- waiting to lock <地址> 目标:使用synchronized申请对象锁未成功,在迚入区等待。
- waiting on <地址> 目标:使用synchronized申请对象锁成功后,释放锁幵在等待区等待。
- parking to wait for <地址> 目标
locked
waiting to lock
waiting on
parking to wait for
park是基本的线程阻塞原语,不通过监视器在对象上阻塞。随concurrent包会出现的新的机制,不synchronized体系不同。
线程动作
线程状态产生的原因:
- runnable:状态一般为RUNNABLE。
- in Object.wait():等待区等待,状态为WAITING或TIMED_WAITING。
- waiting for monitor entry:进入区等待,状态为BLOCKED。
- waiting on condition:等待区等待、被park。
- sleeping:休眠的线程,调用了Thread.sleep()。
Wait on condition 该状态出现在线程等待某个条件的发生。具体是什么原因,可以结合 stacktrace来分析。 最常见的情况就是线程处于sleep状态,等待被唤醒。 常见的情况还有等待网络IO:在java引入nio之前,对于每个网络连接,都有一个对应的线程来处理网络的读写操作,即使没有可读写的数据,线程仍然阻塞在读写操作上,这样有可能造成资源浪费,而且给操作系统的线程调度也带来压力。在 NewIO里采用了新的机制,编写的服务器程序的性能和可扩展性都得到提高。 正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。一种情况是网络非常忙,几 乎消耗了所有的带宽,仍然有大量数据等待网络读 写;另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。所以要结合系统的一些性能观察工具来综合分析,比如 netstat统计单位时间的发送包的数目,如果很明显超过了所在网络带宽的限制 ; 观察 cpu的利用率,如果系统态的 CPU时间,相对于用户态的 CPU时间比例较高;如果程序运行在 Solaris 10平台上,可以用 dtrace工具看系统调用的情况,如果观察到 read/write的系统调用的次数或者运行时间遥遥领先;这些都指向由于网络带宽所限导致的网络瓶颈。