1. 前言

Java Thread Dump 是一个非常有用的应用诊断工具, 通过thread dump出来的信息, 可以定位到你需要了解的线程, 以及这个线程的调用栈. 如果配合linux的top命令, 可以找到你的系统中的最耗CPU的线程代码段, 这样才能有针对性地进行优化.

  1. 场景和实践

2.1. 后台系统一直是在黑盒运行, 除了能暂停一部分任务的执行, 根本无法知道哪些任务耗CPU过多。所以一直以为是业务代码的问题, 经过各种优化(删减没必要的逻辑, 合并写操作)等等优化, 系统负载还是很高. 没什么访问量, 后台任务处理也就是每天几百万的级别, load还是达到了15以上. CPU只有4核,天天收到load告警却无从下手, 于是乎就被迫来分析一把线程.

 
   2.2 系统跑的是java tomcat, 要触发tomcat thread dump很简单, 先找到tomcat对应的进程id, 我们设置为PID
   【linux 命令】:  ps -ef | grep tomcat
   可以找到, 然后给这个进程发送一个QUIT的信号量, 让其触发线程的dump,  下面的操作先别急着动手, 等到看完2.3再动手不迟
    【linux 命令】: kill -3 $PID   /  kill -QUIT $PID
tomcat会把thread dump的内容输出到控制台
     【linux 命令】:cd $tomcathome/logs/
查看 catalina.out 文件, 把最后的跟thread相关的内容获取出来.
大致内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2012-04-13 16:30:41
Full thread dump OpenJDK 64-Bit Server VM (1.6.0-b09 mixed mode):
"TP-Processor12" daemon prio=10 tid=0x00000000045acc00 nid=0x7f19 in Object.wait() [0x00000000483d0000..0x00000000483d0a90]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00002aaab5bfce70> (a org.apache.tomcat.util.threads.ThreadPool$ControlRunnable)
at java.lang.Object.wait(Object.java:502)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:662)
- locked <0x00002aaab5bfce70> (a org.apache.tomcat.util.threads.ThreadPool$ControlRunnable)
at java.lang.Thread.run(Thread.java:636)
 
"TP-Processor11" daemon prio=10 tid=0x00000000048e3c00 nid=0x7f18 in Object.wait() [0x00000000482cf000..0x00000000482cfd10]
java.lang.Thread.State: WAITING (on object monitor)
....
"VM Thread" prio=10 tid=0x00000000042ff400 nid=0x77de runnable"GC task thread#0 (ParallelGC)" prio=10 tid=0x000000000429c400 nid=0x77d9 runnable
 
"GC task thread#1 (ParallelGC)" prio=10 tid=0x000000000429d800 nid=0x77da runnable
 
"GC task thread#2 (ParallelGC)" prio=10 tid=0x000000000429ec00 nid=0x77db runnable
 
"GC task thread#3 (ParallelGC)" prio=10 tid=0x00000000042a0000 nid=0x77dc runnable
 
"VM Periodic Task Thread" prio=10 tid=0x0000000004348400 nid=0x77e5 waiting on condition
 
JNI global references: 815
 
Heap
PSYoungGen      total 320192K, used 178216K [0x00002aaadce00000, 0x00002aaaf1800000, 0x00002aaaf1800000)
eden space 303744K, 55% used [0x00002aaadce00000,0x00002aaae718e048,0x00002aaaef6a0000)
from space 16448K, 65% used [0x00002aaaf0690000,0x00002aaaf110c1b0,0x00002aaaf16a0000)
to   space 16320K, 0% used [0x00002aaaef6a0000,0x00002aaaef6a0000,0x00002aaaf0690000)
PSOldGen        total 460992K, used 425946K [0x00002aaab3a00000, 0x00002aaacfc30000, 0x00002aaadce00000)
object space 460992K, 92% used [0x00002aaab3a00000,0x00002aaacd9f6a30,0x00002aaacfc30000)
PSPermGen       total 56192K, used 55353K [0x00002aaaae600000, 0x00002aaab1ce0000, 0x00002aaab3a00000)
object space 56192K, 98% used [0x00002aaaae600000,0x00002aaab1c0e520,0x00002aaab1ce0000)
 
最后一段是系统的对内存的使用情况.
 
2.3. 要知道thread dump是不会告诉你每个线程的负载情况的, 需要知道每个线程的负载情况, 还得靠top命令来查看.
    【linux 命令】:top -H -p $PID
这时候, 可以看到java进程下各个线程的负载和内存等使用情况. 也不用全部搞下来, 只要top几个负载过高的记录即可(最好按下SHIFT+T 按CPU耗时总时间倒序排序,这样找到的top几个是最耗CPU时间的,而且系统启动时间应该持续15分钟以上,这样容易看出哪个线程耗时多。)
     大致内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Tasks: 118 total,   2 running, 116 sleeping,   0 stopped,   0 zombie
Cpu(s): 92.6%us,  2.3%sy,  0.0%ni,  3.8%id,  0.7%wa,  0.1%hi,  0.7%si,  0.0%st
Mem:   4054168k total,  3892212k used,   161956k free,   115816k buffers
Swap:  4192956k total,   294448k used,  3898508k free,  2156024k cachedPID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
8091 admin     16   0 1522m 814m 9660 R 22.3 20.6   4:05.61 java
8038 admin     16   0 1522m 814m 9660 R 10.3 20.6   2:46.31 java
8043 admin     15   0 1522m 814m 9660 3.7 20.6   1:52.04 java
8039 admin     15   0 1522m 814m 9660 0.7 20.6   2:10.98 java
8041 admin     15   0 1522m 814m 9660 0.7 20.6   1:39.66 java
8009 admin     15   0 1522m 814m 9660 0.3 20.6   0:27.05 java
8040 admin     15   0 1522m 814m 9660 0.3 20.6   0:51.46 java
7978 admin     25   0 1522m 814m 9660 0.0 20.6   0:00.00 java
7980 admin     19   0 1522m 814m 9660 0.0 20.6   0:05.05 java
7981 admin     16   0 1522m 814m 9660 0.0 20.6   0:06.31 java
7982 admin     15   0 1522m 814m 9660 0.0 20.6   0:06.50 java
7983 admin     15   0 1522m 814m 9660 0.0 20.6   0:06.66 java
7984 admin     15   0 1522m 814m 9660 0.0 20.6   0:06.87 java
7985 admin     15   0 1522m 814m 9660 0.0 20.6   0:33.82 java
 
几个字段跟top的字段意思是一致的, 就是这里的 PID是 线程在系统里面的ID, 也就是进程每创建一个线程, 不仅进程自己会分配ID, 系统也会的. 接下来的问题排查就是主要根据这个PID来走的.
 
看到上面的部分数据, 当前正在跑的任务中, CPU占用最高的几个线程ID
 
2.4. 如果不借助工具, 自己分析的话, 可以把PID字段从10进制数改为 16进制, 然后到threaddump日志中去查找一把, 找对对应的线程上下文信息, 就可以知道哪段代码耗CPU最多了.
 
比如 8091  的16进制是 1F9B, 查找 thread dump 日志中, nid=0x1F9B 的线程( 这里的nid意思是nativeid, 也就是上面讲的系统为线程分配的ID), 然后找到相关的代码段, 进行优化即可.
比如
 
1
2
3
4
5
"链路检测" prio=10 tid=0x00002aaafa498000 nid=0x1F9B runnable [0x0000000045fac000..0x0000000045facd10]</div>
 
java.lang.Thread.State: RUNNABLE
at cn.emay.sdk.communication.socket.AsynSocket$CheckConnection.run(AsynSocket.java:112)
at java.lang.Thread.run(Thread.java:636)
 
可以看出, 这是一个 发短信的客户端的链路检测引擎的系统负载飙升. (实际上这个线程引起的负载绝不止这么一点.)
 
2.5 第三方的jar包, 我感到顿时泪奔. 接下来是反编译, 看详细的代码… 果然是有一段死循环监听的… 目前是像他们要一份SDK的源代码, 或者要他们进行优化。
 
2.6 使用工具的话, 可以看到更多一点的信息, java的tda工具就是专门分析thread dump的.
 
具体功能自己去挖掘啦.

Java_tomcat thread dump 分析的更多相关文章

  1. 性能分析之-- JAVA Thread Dump 分析综述

    性能分析之-- JAVA Thread Dump 分析综述       一.Thread Dump介绍 1.1什么是Thread Dump? Thread Dump是非常有用的诊断Java应用问题的工 ...

  2. tomcat thread dump 分析【转载】

    前言 Java Thread Dump 是一个非常有用的应用诊断工具, 通过thread dump出来的信息, 可以定位到你需要了解的线程, 以及这个线程的调用栈. 如果配合linux的top命令, ...

  3. 性能分析之– JAVA Thread Dump 分析

    最近在做性能测试,需要对线程堆栈进行分析,在网上收集了一些资料,学习完后,将相关知识整理在一起,输出文章如下. 一.Thread Dump介绍 1.1什么是Thread Dump? Thread Du ...

  4. (转)性能分析之-- JAVA Thread Dump 分析综述

    原文链接:http://blog.csdn.net/rachel_luo/article/details/8920596 最近在做性能测试,需要对线程堆栈进行分析,在网上收集了一些资料,学习完后,将相 ...

  5. 通过 thread dump 分析找到高CPU耗用与内存溢出的Java代码

    http://heylinux.com/archives/1085.html通过 thread dump 分析找到高CPU耗用与内存溢出的Java代码 首先,要感谢我的好朋友 钊花 的经验分享. 相信 ...

  6. java jvm heap dump及 thread dump分析

    一.概念: 在进行java应用故障分析时,经常需要分析内存和cpu信息,也就说所谓的heap dump 和 thread dump heap dump: heap dump文件是一个二进制文件,需要工 ...

  7. tomcat thread dump 分析

    前言 Java Thread Dump 是一个非常有用的应用诊断工具, 通过thread dump出来的信息, 可以定位到你需要了解的线程, 以及这个线程的调用栈. 如果配合linux的top命令, ...

  8. java之Thread Dump分析

    什么是Thread Dump Thread Dump是非常有用的诊断Java应用问题的工具.每一个Java虚拟机都有及时生成所有线程在某一点状态的thread-dump的能力,虽然各个 Java虚拟机 ...

  9. jstack生成的Thread Dump日志线程 分析

    文章转载自: https://www.javatang.com/archives/2017/10/25/36441958.html 前面文章中只分析了Thread Dump日志文件的结构,今天针对日志 ...

随机推荐

  1. React-Native 之 环境配置和简单使用

    # 前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会 ...

  2. 使用DOS访问数据库详解

    今天突发奇想,想是否可以用DOS命令来操作本地数据库或者连接其他外地数据库,网上搜了很多教程比较繁琐,自己想写一篇文章详细叙述一下,也为以后复习做点备份. 工具: 电脑 win7 64bit MySQ ...

  3. centos7连接阿里云长时间连接不上

    一.手动修改网卡配置 手上有几台centos7的linux,当连接阿里云的ecs服务器时候长时间连接不上,最后失败的问题. 使用 -vvv参数到如下语句就卡着不动了 ssh -vvv XXX.XXX. ...

  4. java基础18 String字符串和Object类(以及“equals” 和 “==”的解析)

    一.String字符串 问:笔试题:new String("abc")创建了几个对象?答:两个对象,一个对象是 位于堆内存,一个对象位于字符串常量池 class Demo17 { ...

  5. python基础学习之路No.4 数据转换以及操作

    练习python的时候经常会用到一些不同数据类型之间的转换操作 搜集了一些资料,整理如下 函数 描述 int(x [,base]) 将x转换为一个整数 long(x [,base] ) 将x转换为一个 ...

  6. 一篇文章读懂开源web引擎Crosswalk-《转载》

    前言 Web技术的优势早已被广大应用开发者熟知,比如可与云服务轻松集成,基于响应式UI设计的精美布局,高度的开放性,跨平台能力, 高效的分发与部署等等.伴随着移动互联网的快速发展与HTML5技术的逐步 ...

  7. NFS服务简介

    NFS服务简介 NFS是Network File System的缩写,即网络文件系统.NFS是由Sun开发并发展起来的一项用于在不同机器,不同操作系统之间通过网络互相分享各自的文件.NFS serve ...

  8. WordPress用户登录后重定向到指定页面

    这篇文章将向您展示WordPress用户登录后如何重定向到指定页面或者文章的技巧. 一.重定向到网站管理面板. 将以下代码添加到您的当前主题的 functions.php 文件中: function  ...

  9. Chrome-Adobe Flash 无法正常使用

    https://support.google.com/chrome/answer/6258784 该网站因是是google.com,被强了,所以一般打不开. 故将google官方说明记录以下: 如果 ...

  10. 【转】实践最有效的提高Android Studio运行、编译速度方案

    原文:https://blog.csdn.net/xwh_1230/article/details/60961723 实践最有效的提高Android Studio运行.编译速度方案 最有效提升Andr ...