常用Java命令——jstack

jstack命令

语法格式
jstack [ option ] pid 
jstack [ option ] executable core
jstack [ option ] [[email protected]]remote-hostname-or-IP
命令行选项。
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的系统调用的次数或者运行时间遥遥领先;这些都指向由于网络带宽所限导致的网络瓶颈。(来自 http://www.blogjava.net/jzone/articles/303979.html