Java运行状态分析2:获取线程状态及堆栈信息

Wesley13
• 阅读 782

Java运行状态分析2:线程状态及堆栈信息

基本概念

出现内存泄漏或者运行缓慢场景,有时候无法直接从业务日志看出问题时候,需要分析jvm内存和线程堆栈

线程堆栈信息主要记录jvm线程在某时刻线程执行情况,分析线程状态可以跟踪到程序出问题的地方 ​ 内存堆栈信息主要记录jvm堆中在某时刻对象使用情况,主要用于跟踪是哪个对象占用了太多的空间,从而跟踪导致内存泄漏的地方

跟踪线程信息

查看当前线程数量

actuator

1.x

http://host:port/metrics/threads //当前进程的线程数 http://host:port/metrics/threads.daemon //当前进程后台驻留线程数 http://host:port/metrics/threads.peak //当前进程线程数峰值

2.x

http://host:port/actuator/metrics/jvm.threads.daemon //当前进程后台驻留线程数 http://host:port/actuator/metrics/jvm.threads.live //当前进程的线程数 http://host:port/actuator/metrics/jvm.threads.peak //当前进程线程数峰值

hystrix 线程状态

如果接入了turbine可以直接通过turbine查看整个集群状态

Java运行状态分析2:获取线程状态及堆栈信息

当集群较大的时候,单纯想看hystrix线程池状态,可以单独从hystrix监控统计类里面获取

http://host:port/sys/hystrix/threads

源码如下:

import com.alibaba.fastjson.JSON; import com.netflix.hystrix.HystrixThreadPoolMetrics; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; ​ import java.util.List; import java.util.stream.Collectors; ​ /** * @author yugj * @date 19/5/5 22:17. */ @RestController @RequestMapping(path = "/sys/hystrix") @ManagedResource(description = "hystrix Endpoint") @EnableScheduling public class HystrixThreadPoolEndpoint { ​    private boolean showStats = false; ​    private static final Logger log = LoggerFactory.getLogger(HystrixThreadPoolEndpoint.class); ​ ​    @GetMapping(value = "/threads")    public List threadStats() { ​        return HystrixThreadPoolMetrics.getInstances().stream().map((m) -> { ​            final HystrixThreadStats stats = new HystrixThreadStats();            stats.poolName = m.getThreadPoolKey().name();            stats.cumulativeExecuted = m.getCumulativeCountThreadsExecuted();            stats.currentActiveCount = m.getCurrentActiveCount().intValue();            stats.currentCompletedCount = m.getCurrentCompletedTaskCount().intValue();            stats.currentCorePoolSize = m.getCurrentCorePoolSize().intValue();            stats.currentLargestPoolSize = m.getCurrentLargestPoolSize().intValue();            stats.currentMaxPoolSize = m.getCurrentMaximumPoolSize().intValue();            stats.currentPoolSize = m.getCurrentPoolSize().intValue();            stats.currentQueueSize = m.getCurrentQueueSize().intValue();            stats.currentTaskCount = m.getCurrentTaskCount().intValue(); ​            return stats;       }).collect(Collectors.toList());   } ​    @GetMapping(value = "/setShowStats")    public String setShowStats(Boolean showStats) { ​        if (showStats != null) {            this.showStats = showStats;       } ​        return "this.show stats:" + this.showStats;   } ​    @Scheduled(fixedRate = 5000)    public void showStats() { ​        if (showStats) {            List<HystrixThreadPoolEndpoint.HystrixThreadStats> statsList = threadStats();            log.info("thread stats :{}", JSON.toJSONString(statsList));       }   } ​    class HystrixThreadStats {        private String poolName;        private Long cumulativeExecuted;        private Integer currentActiveCount;        private Integer currentCompletedCount;        private Integer currentCorePoolSize;        private Integer currentLargestPoolSize;        private Integer currentMaxPoolSize;        private Integer currentPoolSize;        private Integer currentQueueSize;        private Integer currentTaskCount; ​        public String getPoolName() {            return poolName;       } ​        public void setPoolName(String poolName) {            this.poolName = poolName;       } ​        public Long getCumulativeExecuted() {            return cumulativeExecuted;       } ​        public void setCumulativeExecuted(Long cumulativeExecuted) {            this.cumulativeExecuted = cumulativeExecuted;       } ​        public Integer getCurrentActiveCount() {            return currentActiveCount;       } ​        public void setCurrentActiveCount(Integer currentActiveCount) {            this.currentActiveCount = currentActiveCount;       } ​        public Integer getCurrentCompletedCount() {            return currentCompletedCount;       } ​        public void setCurrentCompletedCount(Integer currentCompletedCount) {            this.currentCompletedCount = currentCompletedCount;       } ​        public Integer getCurrentCorePoolSize() {            return currentCorePoolSize;       } ​        public void setCurrentCorePoolSize(Integer currentCorePoolSize) {            this.currentCorePoolSize = currentCorePoolSize;       } ​        public Integer getCurrentLargestPoolSize() {            return currentLargestPoolSize;       } ​        public void setCurrentLargestPoolSize(Integer currentLargestPoolSize) {            this.currentLargestPoolSize = currentLargestPoolSize;       } ​        public Integer getCurrentMaxPoolSize() {            return currentMaxPoolSize;       } ​        public void setCurrentMaxPoolSize(Integer currentMaxPoolSize) {            this.currentMaxPoolSize = currentMaxPoolSize;       } ​        public Integer getCurrentPoolSize() {            return currentPoolSize;       } ​        public void setCurrentPoolSize(Integer currentPoolSize) {            this.currentPoolSize = currentPoolSize;       } ​        public Integer getCurrentQueueSize() {            return currentQueueSize;       } ​        public void setCurrentQueueSize(Integer currentQueueSize) {            this.currentQueueSize = currentQueueSize;       } ​        public Integer getCurrentTaskCount() {            return currentTaskCount;       } ​        public void setCurrentTaskCount(Integer currentTaskCount) {            this.currentTaskCount = currentTaskCount;       }   } ​ }

linux

ps huH p {pid}|wc -l

jstack生成线程堆栈

当服务cup飙升或者出问题需要从主机层面定位时候,使用top -c 命令查看对应哪个进程占用了过高资源

Java运行状态分析2:获取线程状态及堆栈信息

找到资源占用高的进程

明确需要定位的进程通过如下命令找到对应的进程id

ps aux|grep {application alias}

可以通过如下命令定位具体高load线程:

查询进程具体哪个线程占用高load top -Hp {进程pid} ​ thread id为十六进制格式转十六进制值 printf %x {线程pid} ​ 指定特定行数堆栈信息 jstack {进程id}|grep -A 200 {线程id}

接下来通过jstack导出对应的线程堆栈

jstack 对应参数如下

  • -m to print both java and native frames (mixed mode)

  • -l long listing. Prints additional information about locks

服务器线程相对较多,文件大小较大,一般不会考虑在服务器看,另外这样查也会导致忽略了一些统计信息

通过如下命令导出文件,下载到本地查

jstack -l {pid} >> {dump-file-path}

docker环境涉及一些权限,需要进入docker执行,docker里面进程id根据实际情况,一般会联系运维操作

如何查看 分析dump文件,请看下文

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
Java线程的6种状态及切换(透彻讲解)
Java中线程的状态分为6种。1\.初始(NEW):新创建了一个线程对象,但还没有调用start()方法。2\.运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的
Wesley13 Wesley13
3年前
4、jstack查看线程栈信息
1、介绍利用jps、top、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程查找:FoundoneJavaleveldeadlock即可1、jps获得进程号!(https://oscimg.oschina.net/oscnet/da00a309fa6
Stella981 Stella981
3年前
JVM调优之jstack找出最耗cpu的线程并定位代码
jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用得非常多。下面我们来一个实例找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息,用到的命令有ps、top、printf、jstack、grep。第一步先找出Java进程ID,服务器上的Java应用名称为mrfcenter:root@u
Wesley13 Wesley13
3年前
Java的编程逻辑
1、run()和start()的区别2、线程的基本属性和方法1.id:一个递增的整数,每创建一个线程就加一2.name3.优先级:从1到10,默认为5,会映射到系统中的优先级。数字越大,要优先级越高4.状态: NEW:还没调用start RUNABLE:正在执行run或者正在等待cup分配
Wesley13 Wesley13
3年前
JAVA优化篇 如何从茫茫日志中找到运行缓慢的线程
引入  JAVA提供了一些分析DUMP的工具,比如jmap,visualvm等  JAVA还有寻找线程状态的工具,jstack等  数据库也有检查连接数,连接状态的命令,status,processlist等  代码中也可以添加一些时间的信息,对比信息发现可优化的地方  但这些都不是今天要记录的内容,今天要做的是使用一个比较
Wesley13 Wesley13
3年前
03.Android崩溃Crash库之ExceptionHandler分析
目录总结00.异常处理几个常用api01.UncaughtExceptionHandler02.Java线程处理异常分析03.Android中线程处理异常分析04.为何使用setDefaultUncaughtExceptionHandler前沿上一篇整体介绍了crash崩溃
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
Java命令学习系列(二)——Jstack
jstack是java虚拟机自带的一种堆栈跟踪工具。功能jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。线程出现停顿的时候通过jstack来查看各个线程的调用堆