以一个例子来演示排查服务器cpu占用率过高的问题。

准备

将下面的代码文件上传到服务器上,然后使用javac编译,并使用java命令将程序跑起来。

public class JStackCase {

    public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
executor.submit(new Task());
executor.submit(new Task());
} } class Task implements Runnable { @Override
public void run() {
synchronized (this) {
calculate();
}
} public void calculate() {
int i = 0;
while (true) {
i++;
}
}
}

显然,这段程序会导致CPU占用率较高。接下来,我们进行问题排查。

1.定位进程

使用top命令查看cpu占用情况,默认按cpu使用率从高到低排序。我们发现pid为6624的进程占用了70%的cpu。

[root@localhost bin]# top
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6624 root 20 0 2249296 18380 10704 S 70.0 1.8 6:00.17 java
6723 root 20 0 157716 2112 1472 R 5.0 0.2 0:00.03 top
1 root 20 0 193724 3608 1972 S 0.0 0.4 0:07.07 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:13.54 ksoftirqd/0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
7 root rt 0 0 0 0 S 0.0 0.0 0:00.40 migration/0
8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh
9 root 20 0 0 0 0 S 0.0 0.0 0:04.98 rcu_sched
10 root rt 0 0 0 0 S 0.0 0.0 0:04.42 watchdog/0
12 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs
13 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 netns
14 root 20 0 0 0 0 S 0.0 0.0 0:00.00 khungtaskd
15 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 writeback
16 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kintegrityd
17 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 bioset
18 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kblockd
19 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 md
25 root 20 0 0 0 0 S 0.0 0.0 0:10.50 kswapd0
26 root 25 5 0 0 0 S 0.0 0.0 0:00.00 ksmd
27 root 39 19 0 0 0 S 0.0 0.0 0:00.21 khugepaged
28 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 crypto
36 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kthrotld
38 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kmpath_rdacd
39 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kpsmoused

2.定位线程

查看pid为6624的进程下的线程cpu占用情况。发现6634和6635线程几乎占用了大部分的cpu。

[root@localhost bin]# top -Hp 6624
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6634 root 20 0 2249296 16532 8852 R 49.8 1.7 6:34.75 java
6635 root 20 0 2249296 16532 8852 R 49.5 1.7 6:34.69 java
6624 root 20 0 2249296 16532 8852 S 0.0 1.7 0:00.04 java
6625 root 20 0 2249296 16532 8852 S 0.0 1.7 0:00.09 java
6626 root 20 0 2249296 16532 8852 S 0.0 1.7 0:00.01 java
6627 root 20 0 2249296 16532 8852 S 0.0 1.7 0:00.00 java
6628 root 20 0 2249296 16532 8852 S 0.0 1.7 0:00.00 java
6629 root 20 0 2249296 16532 8852 S 0.0 1.7 0:00.00 java
6630 root 20 0 2249296 16532 8852 S 0.0 1.7 0:00.00 java
6631 root 20 0 2249296 16532 8852 S 0.0 1.7 0:00.00 java
6632 root 20 0 2249296 16532 8852 S 0.0 1.7 0:00.00 java
6633 root 20 0 2249296 16532 8852 S 0.0 1.7 0:00.54 java

3.定位代码

接下来jstack就要上场了。可以使用jstack -l [pid]查看线程的堆栈信息。

jstack -l  [pid]  //进程id

当然,我们可以过滤我们只关注的线程的转储信息。

将线程pid转为16进制

因为thread id在栈信息中是以十六进制的形式显示的,所以可以使用printf "%x \n" [pid]命令将线程pid转为16进制。

[root@localhost bin]# printf "%x \n" 6634
19ea
[root@localhost bin]# printf "%x \n" 6635
19eb

过滤19ea线程的堆栈信息,使用jstack -l <pid> | grep <thread-hex-id> -A 10。-A 10 参数用来指定显示行数,否则只会显示一行信息。

[root@localhost bin]# jstack -l 6624 | grep 19ea -A 10
"pool-1-thread-1" #8 prio=5 os_prio=0 tid=0x00007f22e00e4800 nid=0x19ea runnable [0x00007f22d0729000]
java.lang.Thread.State: RUNNABLE
at Task.calculate(JStackCase.java:26)
at Task.run(JStackCase.java:19)
- locked <0x00000000f0a60ff8> (a Task)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)

可以看到定位到代码JstackCase类中第26行。接下来在分析对应的代码即可。

通常,在线上环境远比这复杂,所以需要多次获取线程堆栈信息,进行对比综合分析。所以,仅仅单独分析一个文件是可能并没有太大意义的。

当然我们也可以使用其它的工具来排查问题,比如系统自带的perf,Alibaba开源的工具Arthas等。

使用jstack排查线程问题的更多相关文章

  1. jstack(查看线程)、jmap(查看内存)和jstat(性能分析)

    公司内部同事分享的一篇文章 周末看到一个用jstack查看死锁的例子.昨天晚上总结了一下jstack(查看线程).jmap(查看内存)和jstat(性能分析)命令.供大家参考 1.Jstack 1.1 ...

  2. jstack(查看线程)、jmap(查看内存)和jstat(性能分析)命令

    jstack(查看线程).jmap(查看内存)和jstat(性能分析)命令   公司内部同事分享的一篇文章 周末看到一个用jstack查看死锁的例子.昨天晚上总结了一下jstack(查看线程).jma ...

  3. 命令:jstack(查看线程)、jmap(查看内存)和jstat(性能分析)命令

    命令:jstack(查看线程).jmap(查看内存)和jstat(性能分析)命令 这些命令 必须 在 linux jdk bin 路径 下执行 eq: ./jstack 10303 即可  如果想把 ...

  4. 转: 如何使用jstack分析线程状态

    这个讲的好系列:  如何使用jstack分析线程状态 转:http://www.jianshu.com/p/6690f7e92f27 背景 记得前段时间,同事说他们测试环境的服务器cpu使用率一直处于 ...

  5. jstack分析线程死锁

    一.介绍 jstack是java虚拟机自带的一种堆栈跟踪工具.jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项&qu ...

  6. jstack和线程dump分析

    转自:http://jameswxx.iteye.com/blog/1041173 一:jstack jstack命令的语法格式: jstack  <pid>.可以用jps查看java进程 ...

  7. java jstack dump 线程 介绍 解释

    最近抽时间把JVM运行过程中产生的一些线程进行了整理,主要是围绕着我们系统jstack生成的文件为参照依据.  前段时间因为系统代码问题,造成性能到了天花板,于是就dump了一份stack出来进行分析 ...

  8. Java内存泄漏分析系列之一:使用jstack定位线程堆栈信息

    原文地址:http://www.javatang.com 前一段时间上线的系统升级之后,出现了严重的高CPU的问题,于是开始了一系列的优化处理之中,现在将这个过程做成一个系列的文章. 基本概念 在对J ...

  9. 使用 jstack 查询线程死锁错误日志 定位问题

    定位问题 (1) 首先 找到相应的进程 使用 ps -ef | grep 'com.sankuai.qcs.regulation.dispatch' 找到进程的ID;==>21980 (2) t ...

随机推荐

  1. 如何从Word带图粘贴到编辑器中

    这种方法是servlet,编写好在web.xml里配置servlet-class和servlet-mapping即可使用 后台(服务端)java服务代码:(上传至ROOT/lqxcPics文件夹下) ...

  2. asp.net选择文件夹上传

    HTML部分 <%@PageLanguage="C#"AutoEventWireup="true"CodeBehind="index.aspx. ...

  3. 透明的LISTVIEW

    .NET就是封装的太密了,有时很多时候让我们反而更麻烦,特别是COPY不到的时候,又不懂自已想的话,说土一点就是死路一条, 记得以前经常用一句话,C++支持,可C#他不支持啊!就这样安慰自已 其实做多 ...

  4. laravel5.6操作数据curd写法(查询构建器)

    laravel5.6 数据库操作-查询构建器 <?php //laravel5.6 语法 demo示例 namespace App\Http\Controllers;//命名该控制App空间下名 ...

  5. videojs实践--兼容ie7,8

    1,还是先上图 ie9+,ff,chrome,,,

  6. JMeter 分布式调度压测部署

    我们遇到jmeter被假死死了,这里有2个原因,一是jmeter原本是java写的,heap受硬件限制需要调优,二是单机无法分解超大并发比如100万+并发压测,因此,我们分二部走,首先我们需要进行jm ...

  7. NOIP 2010 P1514 引水入城

    题目:传送门 题目概要:有一个n行m列的矩阵,每一个格子都有一个高度,路径只能从高处向低处扩散,问你如果最后一行可以全部被覆盖,最少要从第一行多少个格子开始,如果不能使最后一行全部被覆盖,求有多少个格 ...

  8. Nodejs - 交互式管理 Node.js 版本

    n - npm:Interactively Manage Your Node.js Versions. Unfortunately n is not supported on Windows. npm ...

  9. Oracle-数据表对象

    表一般指的是一个关系表,也可以生成对象表以及临时表.齐总,对象表是通过用户定义的数据类型生成的,临时表用于存储专用于某个事务或会话的临时数据 字符类型: 定长:char (1-2000字节) 变长:v ...

  10. 笨方法学Python 错误记录

    ex8:忘记输入“空格”ex9:忘记输入“冒号”ex14:%前后要空格,否则errorex21:多个函数嵌套,漏写括号)ex24:%d,漏写d,导致程序错误:"""之间的 ...