一、windows场景:
查看java进程的pid:
![]()
jps
查看并dump出线程堆栈信息,在DOS窗口中显示:
jstack PID
或者直接将日志信息输出到文件(管理员身份):
-l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况
-m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法)
我们一般使用-l参数就可以满足需要
格式如下 Jstack -l PID >> 123.txt
在linux环境下,可以通过top
命令查看各个进程的cpu使用情况,默认按cpu使用率排序
![]()
二、linux场景:
在linux环境下,可以通过top
命令查看各个进程的cpu使用情况,默认按cpu使用率排序
![](https://i-blog.csdnimg.cn/blog_migrate/8a1b6777ce6994288114ff247c63724f.webp?x-image-process=image/format,png)
https://i-blog.csdnimg.cn/blog_migrate/8a1b6777ce6994288114ff247c63724f.webp?x-image-process=image/format,png
1、上图中可以看出pid为23344的java进程占用了较多的cpu资源;
2、通过top -Hp 23344
可以查看该进程下各个线程的cpu使用情况;
http://upload-images.jianshu.io/upload_images/2184951-831f6716e5801e63.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
上图中可以看出pid为25077的线程占了较多的cpu资源,利用jstack命令可以继续查看该线程当前的堆栈状态。
jstack命令
通过top命令定位到cpu占用率较高的线程之后,继续使用jstack pid
命令查看当前java进程的堆栈状态
http://upload-images.jianshu.io/upload_images/2184951-4abd1324fb6e8b7f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
jstack命令生成的thread dump信息包含了JVM中所有存活的线程,为了分析指定线程,必须找出对应线程的调用栈,应该如何找?
在top命令中,已经获取到了占用cpu资源较高的线程pid,将该pid转成16进制的值,在thread dump中每个线程都有一个nid,找到对应的nid即可;隔段时间再执行一次stack命令获取thread dump,区分两份dump是否有差别,在nid=0x246c的线程调用栈中,发现该线程一直在执行JstackCase类第33行的calculate方法,得到这个信息,就可以检查对应的代码是否有问题。
首先要清楚线程的状态
线程的状态有:
new、runnable、running、waiting、timed_waiting、blocked、dead
线程状态变迁图:
各状态说明:
New
: 当线程对象创建时存在的状态,此时线程不可能执行;
Runnable
:当调用thread.start()后,线程变成为Runnable状态。只要得到CPU,就可以执行;
Running
:线程正在执行;
Waiting
:执行thread.join()或在锁对象调用obj.wait()等情况就会进该状态,表明线程正处于等待某个资源或条件发生来唤醒自己;
Timed_Waiting
:执行Thread.sleep(long)、thread.join(long)或obj.wait(long)等就会进该状态,与Waiting的区别在于Timed_Waiting的等待有时间限制;
Blocked
:如果进入同步方法或同步代码块,没有获取到锁,则会进入该状态;
Dead
:线程执行完毕,或者抛出了未捕获的异常之后,会进入dead状态,表示该线程结束
其次,对于jstack日志,我们要着重关注如下关键信息
Deadlock
:表示有死锁
Waiting on condition
:等待某个资源或条件发生来唤醒自己。具体需要结合jstacktrace来分析,比如线程正在sleep,网络读写繁忙而等待
Blocked
:阻塞
Waiting on monitor entry
:在等待获取锁
in Object.wait()
:获取锁后又执行obj.wait()放弃锁
对于
Waiting on monitor entry
和
in Object.wait()的详细描述
:Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。从下图中可以看出,每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 "Active Thread",而其它线程都是 "Waiting Thread",分别在两个队列 " Entry Set"和 "Wait Set"里面等候。在 "Entry Set"中等待的线程状态是 "Waiting for monitor entry",而在 "Wait Set"中等待的线程状态是 "in Object.wait()"