1、CPU暴增可能原因:
1)JVM GC频繁
2)业务代码 死循环
3)线程数过多
2、CPU暴增查看方法:
1、top
2、top -Hp pid
3、jstack命令
简介
1、jstack命令用于打印指定Java进程、核心文件或远程调试服务器的Java线程的Java堆栈跟踪信息
2、jstack命令可以生成JVM当前时刻的线程快照。线程快照是当前JVM内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等
3、如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题
4、当指定的进程在64位Java虚拟机上运行时,可能需要指定-J-d64选项,例如:jstack -J-d64 -m pid
5、该命令可能在未来的版本中不可用!!!
日志文件分析
1、可以通过 jstack [options] pid >> /xxx/xx/x/dump.log命令,将堆栈信息输出到dump.log文件后,然后下载到本地排查文件
options参数说明:
-F:当 jstack [-l] pid 没有响应时,强制打印一个堆栈转储
-l:打印关于锁的其他信息,比如拥有的java.util.concurrent ownable同步器的列表
-m:打印包含Java和本机C/ C++帧的混合模式堆栈跟踪
-h/-help:打印帮助信息
2、在dump.log日志文件里,需要重点关注的线程状态
Deadlock(死锁):死锁线程,一般指多个线程调用间,进入相互资源占用,导致一直等待无法释放的情况
3、日志分析
Found one Java-level deadlock说明发现了一个死锁
waiting to lock Monitor@0x0000000018593468 表示 线程A正在等待给Monitor@0x0000000018593468上锁,但是Monitor@0x0000000018593468被线程B持有。
waiting to lock Monitor@0x0000000018590c88 表示线程B正在等待给Monitor@0x0000000018590c88上锁,但是Monitor@0x0000000018590c88被线程A持有。
从上图可以知道,线程A正在等待锁,但是这个锁被线程B持有;而线程B也在等待锁,但是这个锁被线程A持有。线程A和现场B只能一直等待下去,造成了死锁。
state = BLOCKED 表明线程的状态是阻塞的。
通过com.example.MyThreadB.run() @bci=69, line=47 (Interpreted frame) 和com.example.MyThreadA.run() @bci=69, line=29 (Interpreted frame)定位到了出现死锁的具体的类和行数。
Waiting on condition(等待资源)
该状态出现在线程等待某个条件的发生。最常见的情况是线程在等待网络的读写,比如当网络数据没有准备好读时,线程处于这种等待状态。而一旦有数据准备好读之后,线程会重新激活,读取并处理数据。
如果发现有大量的线程都在处在 Wait on condition,从线程堆栈看,正等待网络读写,这可能是一个网络瓶颈的征兆,因为网络阻塞导致线程无法执行,原因有两种:一种情况是网络非常忙,几 乎消耗了所有的带宽,仍然有大量数据等待网络读写;另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。
另外一种出现 Wait on condition的常见情况是该线程在 sleep,等待 sleep的时间到了时候,将被唤醒。
Waiting on monitor entry(等待获取监视器)
Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。
Blocked(阻塞)
线程阻塞,是指当前线程执行过程中,所需要的资源长时间等待却一直未能获取到,被容器的线程管理器标识为阻塞状态,可以理解为等待资源超时的线程。