以一个例子来演示排查服务器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. django的安装和初步使用

    安装参考:步骤也可以参考这个 很详细 https://blog.csdn.net/zww1984774346/article/details/54408759 如果想在终端查看项目结构 需要用到tre ...

  2. vue框架搭建--axios使用

    前后端数据交互作为项目最基础需求(静态的除外),同时也是项目中最重要的需求. 本文重点介绍axios如何配合vue搭建项目框架,而axios的详细使用介绍请移步使用说明 1.安装 cnpm insta ...

  3. asp.net文件断点上传

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

  4. Cocoapods组件化之搭建组件化项目框架

    一,概述 随着公司业务需求的不断迭代发展,工程的代码量和业务逻辑也越来越多,原始的开发模式和架构已经无法满足我们的业务发展速度了,这时我们就需要将原始项目进行一次重构大手术了.这时我们应该很清晰这次手 ...

  5. [CSP-S模拟测试]:Seat(概率DP+数学)

    题目描述 有$n+2$个座位等距地排成一排,从左到右编号为$0$至$n+1$.最开始时$0$号以及$n+1$号座位上已经坐了一个小$G$,接下来会有$n$个小$G$依次找一个空座位坐下.由于小$G$们 ...

  6. eclipse 启动 tomcat 报错:Server mylocalhost was unable to start within 45 seconds

    这个专门转载一篇博文也是为了讽刺一下自己二逼的程序员职业,哈哈. eclipse启动tomcat服务器报错:Server mylocalhost was unable to start within ...

  7. python list,dic,json型字符串转为list,dict,json

    import ast strr='{"1":"A","3":"B"}' dicts= ast.literal_eval( ...

  8. ORA-01578: ORACLE 数据块损坏 (文件号 10, 块号 57896)ORA-01110: 数据文件 10: '/data/oradata/prod35.dbf'

    https://community.oracle.com/thread/3540795 概述 ------------- 数据库坏块(corruption) 的类型可以按照坏块所属对象的不同,分为用户 ...

  9. java 虚方法。 后面new 那个类, 就调用哪个类的方法 ,而非定义类的方案。 关于父子 类的 呵呵

    java   虚方法.     后面new  那个类, 就调用哪个类的方法 ,而非定义类的方案.  关于父子 类的   呵呵 在多态的情况下,声明为父类类型的引用变量只能调用父类中的方法,但如果此变量 ...

  10. 16/7/27-PHP环境配置(php5.5.3.7+mysql5.7.12+Apache2.4)

    非常感谢http://www.cnblogs.com/jicheng1014/archive/2012/01/26/2329531.html 配置php环境问题 php.ini 路径 "\& ...