【JVM】jstack命令使用

在Java应用的性能测试中,很多性能问题可以通过观察线程堆栈来发现,Jstack是JVM自带dump线程堆栈的工具,很轻量易用,并且执行时不会对性能造成很大的影响。灵活的使用jstack可以发现很多隐秘的性能问题,是定位问题不可多得的好帮手。

1、线程堆栈

   线程堆栈也称为线程调用堆栈。Java线程堆栈是虚拟机中线程(包括锁)状态的一个瞬间的快照,即系统在某个时刻所有线程的运行状态,包括每一个线程的调用堆栈,锁的持有情况等信息。从线程堆栈中可以得到以下信息

      a.线程的名字,ID,线程的数量等

      b.线程的运行状态,锁的状态(锁被哪个线程持有,哪个线程在等待锁等)

      c.函数间的调用关系,包括完整类名,所执行的方法,源代码的行数等等

2、命令使用

  jstack <pid>  >filename : 获取应用运行时的线程堆栈

 说明:pid为应用进程号

 对于java应用而言,以下常见的几个性能问题都可以从线程堆栈入手定位

  • 系统挂起无响应
  • 系统cpu较高
  • 系统运行的响应时间长
  • 线程死锁等

3、线程的运行状态

 常用到的几个线程状态有 RUNNABLE、BLOCKED、WAITING、TIMED_WAITING

 RUNNABLE

 RUNNABLE状态表示线程正处于运行状态。一般情况下处于运行状态线程是会消耗CPU的,但不是所有的RUNNABLE都会消耗CPU, 比如线程进行网络IO时,这时线程状态是挂起的,但由于挂起发生在本地代码,虚拟机并不感知,所以不会像显示调用Java的sleep()或者wait()等方法进入WAITING状态,只有等数据到来时才消耗一点CPU。

TIMED_WAITING/WAITING

 这两种状态表示线程被挂起,等待被唤醒,当设置超时时间时状态为TIMED_WAITING,如果未设置超时时间,这时的状态为WAITING,必须等待lock.notify()或lock.notifyAll()或接收到interrrupt信号才能退出等待状态。

 TIMED_WAITING/WAITING下还需要关注下面几个线程状态:

  • waiting on condition : 说明线程等待另一个条件的发生,来把自己唤醒
  • on object monitor :说明该线程正在执行obj.wait()方法,放弃了Monitor, 进入" Wait Set "队列

BLOCKED

此时的线程处于阻塞状态,一般是在等待进入一个人临界区 "waiting for monitor entry'",这种状态是需要重点关注的

4、哪些线程状态占用CPU

处于TIMED_WAITING、WATING、BLOCKED状态的线程是不消耗CPU的,而处于RUNNABLE状态的线程要结合当前代码的性质判断是否消耗CPU

  • 纯java运算代码,并且未被挂起,是消耗CPU的
  • 网络IO操作,在等待数据时是不消耗CPU的

参考地址

jstack性能问题定位案例分析详解 :https://blog.csdn.net/qq_30353203/article/details/76690272

原文地址:https://www.cnblogs.com/kiko2014551511/p/12883992.html