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:




java 堆栈设置查询 java看堆栈命令_java 堆栈设置查询



jstack 命令(这里只截取了部分图片)




java 堆栈设置查询 java看堆栈命令_对象锁_02




线程状态


jstack是java虚拟机自带的一种堆栈跟踪工具,所以 jstack 命令主要用来查看Java线程的调用堆栈的,可以用来分析线程问题(如死锁)。当我们使用 jstack 命令查看线程堆栈信息时可能会看到这几种状态:


  • NEW:未启动的。不会出现在Dump中
  • RUNNABLE:在虚拟机内执行的
  • BLOCKED:受阻塞并等待监视器锁
  • WATING:无限期等待另一个线程执行特定操作
  • TIMED_WATING:有时限的等待另一个线程的特定操作
  • TERMINATED:已退出的

Moitor


Monitor 是 Java中用以实现线程之间的互斥与协作的主要手段 ,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。下 面这个图,描述了线程和 Monitor之间关系,以 及线程的状态转换图:



java 堆栈设置查询 java看堆栈命令_Java_03



进入区(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



java 堆栈设置查询 java看堆栈命令_java 堆栈设置查询_04



waiting to lock



java 堆栈设置查询 java看堆栈命令_Java_05



waiting on



java 堆栈设置查询 java看堆栈命令_java 堆栈设置查询_06



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的系统调用的次数或者运行时间遥遥领先;这些都指向由于网络带宽所限导致的网络瓶颈。