在大型的应用中,线程堆栈打印出来特别多,如何从众多的信息中找到真正有用,有价值的信息,我们需要一定的技巧。本文对此详细介绍。

我们可以从三个方面分析:堆栈的局部信息,一次堆栈的统计信息,多个堆栈的对比信息。

  • 从一次的堆栈信息中,我们可以直接获取以下信息:

    • 每一个线程的调用关系,当前线程在调用哪些函数
    • 每个线程的当前状态,持有哪些锁,在等待哪些锁?
  • 从一次堆栈信息中,我们还可以统计以下信息:
    • 是否有很多线程都在等待同一个锁,说明这个系统存在性能瓶颈,导致了锁竞争
    • 当前线程的总数量
    • 大多数线程在干什么,在执行什么代码?
  • 从多次的堆栈信息中,可以得到以下信息:
    • 一个线程是否长期执行,如果每次打印堆栈某个线程一直处于同样的调用上下文中,那么说明这个线程一直执行这段代码,此时要根据代码逻辑检查,是否合理。
    • 某个线程是否长期存在获取不到锁的情况,线程是否永远得不到唤醒,如果某一个线程一直等在一个锁,就要检查占用这个锁的线程为什么不释放。

如果说打印一次线程堆栈是平面,那么打印多次就是立体了,我们可以看到一段运行的情况。

接下来从以下几个方面分析:

  • 线程死锁分析
  • java代码导致的cpu过高分析
  • 死循环分析
  • 资源不足分析性能瓶颈分析

线程死锁分析

线程死锁的原因:当两个或者多个线程正在等待被对方占用的锁,死锁就会发生。在时间0的时候,线程0占用lock0锁,线程1占用lock1锁。在时间1,进行了其它操作,在时间2,线程0,1企图持有对方的锁,但是由于2个锁已经在时间0被锁住,所以只能等待释放。由于这两个线程互相要等待被对方占有的锁,自己才能继续,因此就造成了死锁。
我们看以下示例:
从打印的堆栈信息可以看到第一行,found one java-level deadlock ,如果线程存在死锁情况,堆栈会直接给出死锁的分析结果。从堆栈信息中可以看到,TestThread2中持有锁<0x22bffb10>但在等待锁<0x22bffb08>,相反,TestThread2中持有锁<0x22bffb08>,但在等待锁<0x22bffb10>。这里说的死锁是真正意义上的死锁,由于代码的错误导致的,严重程度取决于线程执行什么性质的功能代码,如果是关键功能,可能造成整个系统的瘫痪。死锁的2个或者多个线程是不消耗cpu的,所以认为死锁会导致cpu100%是错误的。

Java代码死循环等导致的cpu过高的分析

当系统负载大的时候会导致cpu过高,但不正确的代码也会导致cpu过高,比如死循环。我们如何从线程堆栈中找到死循环的线程呢?方法就是多次打印堆栈信息,通过对比前后的线程,找到一致运行的线程。具体步骤如下:
  1. 通过上一篇文章介绍过的方法打印第一次堆栈信息
  2. 等待一定时间,再次打印第二次堆栈信息
  3. 预处理2次堆栈信息,首先排除等待状态的线程,这种状态的线程不消耗cpu,前面已经讲过。我们只关注runnable状态的线程。
  4. 比较前后2次预处理后的线程,找出一段时间一直活跃的线程,如果2次堆栈信息在同一个线程处于同样的调用上下文,就列为重点怀疑对象。接下来结合代码逻辑检查该线程执行的上下文所对应的代码是不是属于应该长期运行的代码。
如果通过堆栈定位没有发现可疑代码,那么cpu高可能是不恰当的内存设置导致的频繁gc,从而导致的cpu过高。

资源不足等导致的性能下降分析

这里说的资源包括数据库连接。大多数时候资源不足和性能瓶颈是同一类问题。当资源不足,就会导致资源的竞争,请求该资源的线程会被阻塞或者挂起,自然就导致性能下降。系统对于资源,一般的设计模式是:当需要资源的时候,获取资源,当不需要的时候就把资源释放掉。如果暂时没有可用的资源,就等待在哪里。如果有别的线程释放资源,那么等待的线程被notify,等待的线程获得资源继续运行。一般的资源设计都遵循wait/notify模式。如果资源不足,那么有大量的线程等待资源,打印的线程堆栈如果具有这个特征,说明该资源存在瓶颈。
  1. 大量的线程停在同样的调用上下文上。
  2. 资源数量配置太小,如数据库连接数,如果系统压力过大,资源不足导致线程不能及时获得资源而等待在那里。
  3. 获得资源的线程把持资源时间太久,导致资源不足。比如把一段和操作数据库无关的代码放在获取数据库连接和释放数据库连接之间。
  4. 设计不合理导致的资源占用太久,比如sql没有加索引导致执行sql太慢。
  5. 资源用完后,没有关闭导致资源泄漏或者减少。
资源不足往往表现出一个现象是系统越来越慢,并最终停止响应,超时。

多个锁导致的锁链分析

很多线程在等待不同的锁,有的锁竞争可能是由于另一锁对象竞争导致,这时候需要找到根源。
  1. 看到有40多个线程在等待锁0xbef17078,首先找到已经占有这把锁的线程thread-196
  2. 看到thread-196占有锁,0xbef17078,但又在等待锁<0xbc7b4110>,那么此时需要再找占有<0xbc7b4110>这个锁的线程,即thread-609。
  3. 那么占有锁<0xbc7b4110>的线程是问题的根源,下一步就是查到底为什么这个线程长时间占有这个锁。可能的原因是持有这把锁的线程正在执行的代码性能比较低,导致占有时间过长。

转载于:https://www.cnblogs.com/firstdream/p/8109275.html

Java问题定位之如何借助线程堆栈进行问题分析相关推荐

  1. 通过 Java 线程堆栈进行性能瓶颈分析

    改善性能意味着用更少的资源做更多的事情.为了利用并发来提高系统性能,我们需要更有效的利用现有的处理器资源,这意味着我们期望使 CPU 尽可能出于忙碌状态(当然,并不是让 CPU 周期出于应付无用计算, ...

  2. java打印线程堆栈_Java问题定位之Java线程堆栈分析

    采用Java开发的大型应用系统越来越大,越来越复杂,很多系统集成在一起,整个系统看起来像个黑盒子.系统运行遭遇问题(系统停止响应,运行越来越慢,或者性能低下,甚至系统宕掉),如何速度命中问题的根本原因 ...

  3. java线程堆栈_深入JVM剖析Java的线程堆栈

    在这篇文章里我将教会你如何分析JVM的线程堆栈以及如何从堆栈信息中找出问题的根因.在我看来线程堆栈分析技术是Java EE产品支持工程师所必须掌握的一门技术.在线程堆栈中存储的信息,通常远超出你的想象 ...

  4. linux查看java堆栈信息_Java运行状态分析2:获取线程堆栈信息

    Java运行状态分析2:获取线程堆栈信息 基本概念 出现内存泄漏或者运行缓慢场景,有时候无法直接从业务日志看出问题时候,需要分析jvm内存和线程堆栈 线程堆栈信息主要记录jvm线程在某时刻线程执行情况 ...

  5. java线程堆栈信息分析

    线程堆栈也称作线程调用堆栈.Java线程堆栈是虚拟机中线程(包括锁)状态的一个瞬间快照,即系统在某个时刻所有线程的运行状态,包括每一个线程的调用堆栈,锁的持有情况等信息.对于已经消失而又没留有痕迹的信 ...

  6. JAVA问题定位跟踪技术

    常用的JAVA调试技巧:  线程堆栈解读  性能瓶颈分析  远程调试  内存泄露检测 常用工具集:  proc工具集  系统跟踪命令truss/strace  Core文件管理coreadm  进程状 ...

  7. JVM:如何分析线程堆栈

    英文原文:JVM: How to analyze Thread Dump 在这篇文章里我将教会你如何分析JVM的线程堆栈以及如何从堆栈信息中找出问题的根因.在我看来线程堆栈分析技术是Java EE产品 ...

  8. Java问题定位技术手册

    点击上方 "大数据肌肉猿"关注, 星标一起成长 后台回复[加群],进入高质量学习交流群 2021年大数据肌肉猿公众号奖励制度 这几天在整理书籍的时候发现了一本古老书籍叫<Ja ...

  9. openjdk-alpine镜像无法打印线程堆栈和内存堆栈问题

    基于openjdk:8u171-alpine构建的java镜像,使用jstack命令打印线程的时候会提示以下错误: /opt # ps -ef PID USER TIME COMMAND 1 root ...

最新文章

  1. iBATIS In Action:使用映射语句(一)
  2. 面试:GET和POST两种基本请求方法有什么区别
  3. sql中set命令解析
  4. eclipse 设置 content type 编码格式
  5. 计算机类高职院校课题,高职院校公共计算机类课程体系构建的教改研究
  6. 《Solution-Centric Organization》解决方案导向型组织 节选 III
  7. Smarty s02
  8. 某省HW中遇到的提权
  9. 数据契约(DataContract)
  10. Postman Request Payload发送请求
  11. Oracle数据库删除重复的记录
  12. 数学建模6 典型相关分析
  13. 向日葵linux版远程怎么打开,使用向日葵app远程控制你的Mac笔记本 之小白使用指导...
  14. 第一弹app v2.30.0
  15. JavaScript分解质因数
  16. iOS 审核 苹果登陆失败
  17. maven dependency problem 问题
  18. can是什么时候处于显性_CAN总线什么情况下为空闲状态? - 全文
  19. html复习第四课(2_34_0924_html)
  20. Cairngorm开发框架

热门文章

  1. 《pytorch》对CIFAR数据集的分类
  2. pytorch实现LeNet5
  3. Torch 学习总结
  4. [深度学习NPL]word2vector总结与理解
  5. python基础教程运行程序_Python入门基础教程:WSGI
  6. Hibernate框架(持久化类、缓存、事务管理)
  7. Struts2数据封装
  8. B. Make it Divisible by 25
  9. python的变量对大小写并不敏感_Python编程基础02:Python基本语法
  10. 计算机软件通常分为两大类 它们是,计算机考试题库:计算机考试练习题(79)...