文档章节

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

yugjcnz
 yugjcnz
发布于 07/16 09:30
字数 1104
阅读 47
收藏 2

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查看整个集群状态

当集群较大的时候,单纯想看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<HystrixThreadStats> 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 命令查看对应哪个进程占用了过高资源

找到资源占用高的进程

明确需要定位的进程通过如下命令找到对应的进程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文件,请看下文

© 著作权归作者所有

yugjcnz
粉丝 1
博文 76
码字总数 28362
作品 0
厦门
程序员
私信 提问
通过jstack日志分析和问题排查

简介 jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁...

谢思华
2018/06/29
619
0
Java 线程转储

软件维护是一个枯燥而又有挑战性的工作。只要软件功能符合预期,那么这个工作就是好的。设想一个这样的情景,你的电话半夜也一直在响(这不是一个令人愉快的感受,是吧?) 任何软件系统,无...

YuanyuanL
2013/11/24
8.8K
22
Android开发高手课之卡顿优化

造成卡顿的原因最后都会反映到CPU时间上,可以把CPU时间分为两种:系统时间和用户时间。 用户时间:执行用户态应用程序代码所消耗的时间 系统时间:执行内核态系统调用所消耗的时间,包括I/O...

小菜鸟程序媛
03/12
0
0
Java线程Dump分析工具--jstack

jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使用方式只支持以下的这种方式: jstack [-l][F] p...

serenity
2015/08/03
192
0
基于 JVMTI 实现 Java 线程的监控

随着多核 CPU 的日益普及,越来越多的 Java 应用程序使用多线程并行计算来充分发挥整个系统的性能。多线程的使用也给应用程序开发人员带来了巨大的挑战,不正确地使用多线程可能造成线程死锁...

红薯
2009/12/15
1K
1

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周一乱弹 —— 熟悉的味道,难道这就是恋爱的感觉

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @xiaoshiyue :好久没分享歌了分享张碧晨的单曲《今后我与自己流浪》 《今后我与自己流浪》- 张碧晨 手机党少年们想听歌,请使劲儿戳(这里)...

小小编辑
今天
265
8
SpringBoot中 集成 redisTemplate 对 Redis 的操作(二)

SpringBoot中 集成 redisTemplate 对 Redis 的操作(二) List 类型的操作 1、 向列表左侧添加数据 Long leftPush = redisTemplate.opsForList().leftPush("name", name); 2、 向列表右......

TcWong
今天
19
0
排序––快速排序(二)

根据排序––快速排序(一)的描述,现准备写一个快速排序的主体框架: 1、首先需要设置一个枢轴元素即setPivot(int i); 2、然后需要与枢轴元素进行比较即int comparePivot(int j); 3、最后...

FAT_mt
昨天
4
0
mysql概览

学习知识,首先要有一个总体的认识。以下为mysql概览 1-架构图 2-Detail csdn |简书 | 头条 | SegmentFault 思否 | 掘金 | 开源中国 |

程序员深夜写bug
昨天
11
0
golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web

micro web micro 功能非常强大,本文将详细阐述micro web 命令行的功能 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go-micro环境, golang微服务框架...

非正式解决方案
昨天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部