程序占用cpu高达99.9%?
那么,怎么有效快速的定位是程序中的哪条线程出了问题,从而精确到具体是哪一行代码出了问题呢?
今天就来get一手新技能,是时候开始装逼了。
主要就针对windows系统和linux系统
首先介绍一个java命令:jstack
jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的常见原因。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情,或者等待着什么资源。
windows系统
首先看一段代码,先假装不知道问题出在哪里啊:
/**
* 演示 cpu 占用过高
*/
public class Demo1_16 {
public static void main(String[] args) {
new Thread(null, () -> {
System.out.println("1...");
while(true) {
}
}, "thread1").start();
new Thread(null, () -> {
System.out.println("2...");
try {
Thread.sleep(1000000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "thread2").start();
new Thread(null, () -> {
System.out.println("3...");
try {
Thread.sleep(1000000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "thread3").start();
}
}
运行后,发现也没有报错,但是cpu使用率就特别高,不用想,肯定代码出问题了。
解决办法:
1.打开任务管理器----->资源监视器
2.找到java进程对应的pid
3.把java进程导出快照,也可不导出直接在窗口查看。直接win+R->cmd->运行命令
导出:jstack -l 13616 > c:/13616.stack
不导出:jstack -l 13616
这里是把java程序运行的信息导出到c盘的13616.stack的文件里。
4.在windows下只能查看进程的cpu占用率,要查看线程的cpu占用率要借助其他的工具,我这里用的是微软提供的 Process Explorer
下载地址http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
下载完,解压,运行procexp.exe,找到占cpu高的java程序,然后右键点击Properties...
5.然后选择 Threads 选项,找到占用cpu高的线程的tid,比如我这里是 7272的线程
6.把tid转换成16进制,我这里直接用系统自带的计算器转换,得到的线程tid的16进制的值为 1C68
。置于为什么要转换呢,是因为先前用jstack导出的信息里面线程对应的tid是16进制的。
7.打开刚导出c盘的13616.stack文件,查找 1C68
8.重点来了
,看问题到底出在哪里
问题就在Demo1_16这个类中的第11行代码。
9.接下来看看源码。
问题找到了解决它就完了。
linux系统
Linux系统相对来说就简单很多了。
1.用top
命令定位哪个进程对cpu的占用过高
如上图:PID为32655
的java进程占用cpu高达99.3,这肯定是有问题的
2.用ps
命令进一步定位是哪个线程引起的cpu占用过高
ps H -eo pid,tid,%cpu | grep 进程id
如上图:找到对应线程的tid为32665
3.输入命令:
jstack 进程id
可以根据线程id 找到有问题的线程,进一步定位到问题代码的源码行号。
4.把上边查到的线程tid32665转成十六进制为7F99
5.查找问题到底出在哪里
<<上一篇:java线程池的运行原理