我们通常会使用工具jstack 去跟踪线程信息,其如何实现使用attach 的方式还是ptrace 的方式,这些可以去参考本人的博客的其他文章。

但这些方式都是外部使用的方式,如何直接使用java代码得到当前进程的线程的信息,方便监控jvm的整个运行状态,就不的不提到了ManagementFactory

通过调用方法

ThreadMXBean tmbean = ManagementFactory.getThreadMXBean();

通过得到 ThreadMXBean 可以得到非常多的thread信息,博客里也主要提到几个重要函数的实现

ThreadMXBean是个接口,主要实现都是在 ThreadImpl.java 里实现。

1. getThreadCount()

在虚拟机里会有ThreadService,里面会有些计数器用于记录总线程数,活着线程数目

PerfCounter*  ThreadService::_total_threads_count = NULL;
PerfVariable* ThreadService::_live_threads_count = NULL;
PerfVariable* ThreadService::_peak_threads_count = NULL;
PerfVariable* ThreadService::_daemon_threads_count = NULL;
volatile int ThreadService::_exiting_threads_count = 0;
volatile int ThreadService::_exiting_daemon_threads_count = 0;

当线程创建,消亡都会调用 ThreadService 的方法来对计数器加减,这样就能直接得到线程数目的状态,而不需要去遍历线程链表。

2. getAllThreadIds()

这个实现也比较简单,直接扫描线程列表,就可以得到每个java 的线程id, 在扫描过程中使用了锁,锁住了线程链表。 但因为从native代码到java代码中没有锁结构,得到线程的列表只能表示当时的状态,当得到id的时候并不能保证该线程依然存活。

ThreadsListEnumerator::ThreadsListEnumerator(Thread* cur_thread,bool include_jvmti_agent_threads,bool include_jni_attaching_threads) {assert(cur_thread == Thread::current(), "Check current thread");int init_size = ThreadService::get_live_thread_count();_threads_array = new GrowableArray<instanceHandle>(init_size);MutexLockerEx ml(Threads_lock);for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) {// skips JavaThreads in the process of exiting// and also skips VM internal JavaThreads// Threads in _thread_new or _thread_new_trans state are included.// i.e. threads have been started but not yet running.if (jt->threadObj() == NULL   ||jt->is_exiting() ||!java_lang_Thread::is_alive(jt->threadObj())   ||jt->is_hidden_from_external_view()) {continue;}// skip agent threadsif (!include_jvmti_agent_threads && jt->is_jvmti_agent_thread()) {continue;}// skip jni threads in the process of attachingif (!include_jni_attaching_threads && jt->is_attaching()) {continue;}instanceHandle h(cur_thread, (instanceOop) jt->threadObj());_threads_array->append(h);}
}

我们也可以看到 JNI attach 的线程,和jvmti agent的线程是不被统计在内的

3. ThreadInfo[] getThreadInfo 得到线程具体的堆栈信息

不论是传入要取的线程列表还是要取的所有的线程列表,最后都会看到将取堆栈信息的任务交给了vm thread 线程处理,关于vm thread的作用可以参考本人的其他博客。

  // Obtain thread dumps and thread snapshot informationVM_ThreadDump op(dump_result,thread_handle_array,num_threads,max_depth, /* stack depth */with_locked_monitors,with_locked_synchronizers);VMThread::execute(&op);

a.  vm thread 去遍历所有线程的信息,由于是单线程处理,如果线程数量多的话是会影响到性能的,因为在扫描堆栈过程中,是在softpoint的状态。

b. ThreadDumpResult dump_result(num_threads); 使用ThreadDumpResult 去存储ThreadSnapshot 而保证不会被gc,因为从vm thread抓取线程结束,在填充threadinfo的时候还是会发生gc。

4. 锁的细节显示

在函数 dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers)里有2个参数 lockedMonitor, 和 lockedSynchronizer

而这两个参数分别控制两种锁ThreadInfo .getLockedMonitors()  和 ThreadInfo.getLockedSynchronizers()

a.  Monitor 锁

就是我们传统使用的synchronized(Object obj),

可以通过MonitorInfo[]得到具体的锁的数量和信息

b. Locked ownable synchronizers 锁

常指的ReentrantLock 和 ReentrantReadWriteLock 锁

通过得到LockInfo[]  可以得到具体的类,锁的数量和信息

JVM源码系列:ThreadMXBean 打出堆栈信息原理分析相关推荐

  1. c++ map 获取key列表_好未来Golang源码系列一:Map实现原理分析

    分享老师:学而思网校 郭雨田 一.map的结构与设计原理 golang中map是一个kv对集合.底层使用hash table,用链表来解决冲突 ,出现冲突时,不是每一个key都申请一个结构通过链表串起 ...

  2. java源码系列:HashMap底层存储原理详解——4、技术本质-原理过程-算法-取模具体解决什么问题

    目录 简介 取模具体解决什么问题? 通过数组特性,推导ascii码计算出来的下标值,创建数组非常占用空间 取模,可保证下标,在HashMap默认创建下标之内 简介 上一篇文章,我们讲到 哈希算法.哈希 ...

  3. 4、Eureka 源码解析 之 Eureka Client 启动原理分析

    在前面的一篇文章 3.Eureka 源码解析 之 Eureka Server 启动原理分析当中我们分析了一下 Eureka Server 的启动.在集群环境下 Eureka Server 相互之前需要 ...

  4. Java多线程--使用ThreadMXBean 打出堆栈信息

    我们通常会使用工具jstack 去跟踪线程信息,其如何实现使用attach 的方式还是ptrace 的方式,这些可以去参考本人的博客的其他文章. 但这些方式都是外部使用的方式,如何直接使用Java代码 ...

  5. Spring IoC 源码系列(五)getBean 流程分析

    一.FactoryBean 用法讲解 在分析源码流程之前,我们先来看一下 FactoryBean,乍一看这家伙和 BeanFactory 很像,它们都可以用来获取 bean 对象,简单来说 Facto ...

  6. vue3源码系列之计算属性computed原理剖析

    前言 vue3诸多API中computed的作用毋庸置疑,也算是我们开发中使用比较多的API了.今天就让我们来探究下computed底层到底做了什么.如果想要学好computed个人觉得还是需要将ef ...

  7. JVM源码系列:JVM内部运行之Class的Method

    1. Class的属性 在JVM中,通常一个class会初始化成Klass(接口), InstanceKlass(实例), Method(方法), ConstantsPool(常量区) 在上图我们可以 ...

  8. java源码系列:HashMap底层存储原理详解——5、技术本质-原理过程-算法-取模会带来一个什么问题?什么是哈希冲突?为什么要用链表?

    目录 取模会带来一个什么问题? 演示什么是哈希冲突(哈希碰撞)? 为什么要用链表? 其他--布隆过滤器 取模会带来一个什么问题? 好,那同学们这样他能达到一个目的,但是呢,它也会带来的一个问题,那它会 ...

  9. Spring源码系列(十二)Spring创建Bean的过程(二)

    1.写在前面 上篇博客主要Spring在创建Bean的时候,第一次调用的Bean的后置处理器的过程,同时笔者也打算将整个Spring创建的Bean的过程,通过这个系列,将Bean的创建过程给讲清楚,废 ...

最新文章

  1. Elastic-Job功能特性
  2. datagrid 什么时候结束编辑_2020年中考结束后,什么时候出分?什么时候报志愿?...
  3. 腾讯TI-ONE平台从cos导入数据到jupyterLab失败
  4. python常用包有哪些品牌_python 常用包总结
  5. poj 3268 bzoj 1631: [Usaco2007 Feb]Cow Party(最短路)
  6. 【语音去噪】基于matlab小波软阈值语音降噪【含Matlab源码 531期】
  7. SECS/GEM协议库开发开源代码
  8. vnc远程软件,盘点六款你值得拥有的vnc远程软件
  9. Baas是什么?区块链Baas平台开发解决方案带你知晓
  10. neo4j学习总结--第三课 Cypher(CQL)命令一
  11. chrome浏览器无法访问此网站并且响应时间长的方法
  12. 2012, PPSN,Geometric Semantic Genetic Programming,GSGP
  13. 延安市基础教育科研规划课题申请•评审书
  14. mysql查询最高分学生年龄_MySQL练习题student_score
  15. Python实现生成多个不同半径、互不重叠的圆形的方法
  16. JavaWeb实现注册登录功能并将用户数据写进数据库(商城系统第一部分)
  17. 一周热图|黄晓明、刘亦菲走进瑞士天梭工厂;卡特彼勒牵手CBA联赛;爱马仕匠心工坊登陆西安...
  18. html 订阅发布,发布订阅模式.html · Avan/blog_demo_defineProperty - Gitee.com
  19. 综合训练(考勤系统)
  20. 从MVP(Product)到MVP(Prototype)

热门文章

  1. 【180621】VC++经典俄罗斯方块游戏源码
  2. Go语言GoString与C中char*的异同
  3. 湖南衡阳电影院起火5层大厦被烧毁(组图)
  4. linux下的c语言实现象棋,【C语言小游戏】 中国象棋
  5. 解决arcgis中Lambert conformal conic projection存在的自动变换地理坐标系问题(可自定义为WGS84等任意地理坐标系)
  6. 微信小程序支付接口报错:appid和openid不匹配
  7. CAD入门学习教程:什么是截取大样?有什么用?
  8. AI语音生成器是下一大安全威胁吗?
  9. 嵩天python测验期末测试_Python数据分析实战_章节测验,期末考试,慕课答案查询公众号...
  10. 质谱高级数据分析工具