JVM源码系列:ThreadMXBean 打出堆栈信息原理分析
我们通常会使用工具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 打出堆栈信息原理分析相关推荐
- c++ map 获取key列表_好未来Golang源码系列一:Map实现原理分析
分享老师:学而思网校 郭雨田 一.map的结构与设计原理 golang中map是一个kv对集合.底层使用hash table,用链表来解决冲突 ,出现冲突时,不是每一个key都申请一个结构通过链表串起 ...
- java源码系列:HashMap底层存储原理详解——4、技术本质-原理过程-算法-取模具体解决什么问题
目录 简介 取模具体解决什么问题? 通过数组特性,推导ascii码计算出来的下标值,创建数组非常占用空间 取模,可保证下标,在HashMap默认创建下标之内 简介 上一篇文章,我们讲到 哈希算法.哈希 ...
- 4、Eureka 源码解析 之 Eureka Client 启动原理分析
在前面的一篇文章 3.Eureka 源码解析 之 Eureka Server 启动原理分析当中我们分析了一下 Eureka Server 的启动.在集群环境下 Eureka Server 相互之前需要 ...
- Java多线程--使用ThreadMXBean 打出堆栈信息
我们通常会使用工具jstack 去跟踪线程信息,其如何实现使用attach 的方式还是ptrace 的方式,这些可以去参考本人的博客的其他文章. 但这些方式都是外部使用的方式,如何直接使用Java代码 ...
- Spring IoC 源码系列(五)getBean 流程分析
一.FactoryBean 用法讲解 在分析源码流程之前,我们先来看一下 FactoryBean,乍一看这家伙和 BeanFactory 很像,它们都可以用来获取 bean 对象,简单来说 Facto ...
- vue3源码系列之计算属性computed原理剖析
前言 vue3诸多API中computed的作用毋庸置疑,也算是我们开发中使用比较多的API了.今天就让我们来探究下computed底层到底做了什么.如果想要学好computed个人觉得还是需要将ef ...
- JVM源码系列:JVM内部运行之Class的Method
1. Class的属性 在JVM中,通常一个class会初始化成Klass(接口), InstanceKlass(实例), Method(方法), ConstantsPool(常量区) 在上图我们可以 ...
- java源码系列:HashMap底层存储原理详解——5、技术本质-原理过程-算法-取模会带来一个什么问题?什么是哈希冲突?为什么要用链表?
目录 取模会带来一个什么问题? 演示什么是哈希冲突(哈希碰撞)? 为什么要用链表? 其他--布隆过滤器 取模会带来一个什么问题? 好,那同学们这样他能达到一个目的,但是呢,它也会带来的一个问题,那它会 ...
- Spring源码系列(十二)Spring创建Bean的过程(二)
1.写在前面 上篇博客主要Spring在创建Bean的时候,第一次调用的Bean的后置处理器的过程,同时笔者也打算将整个Spring创建的Bean的过程,通过这个系列,将Bean的创建过程给讲清楚,废 ...
最新文章
- 人工智能学习知识框架(知识点、实际应用)-思维导图汇总-xmind原图
- [MATLAB粒子模拟笔记]差分泊松方程求静电场分布
- java三目运算符嵌套_替代JS中的嵌套三元运算符
- javascript --- 实现Ajax的代码
- 趣挨踢 | 跳槽季,让我们一起攻克算法吧!
- 工业机器人演示码垛和卸垛_众多企业购买自动码垛机的原因是什么?
- 文本模式下安装Oracle 10g
- 电脑工具栏怎么调整到下面_PDF格式的合同怎么盖公章?这不是在为难我胖虎吗?...
- pku2192(并查集+枚举)
- 腾讯视频怎么获得html代码,如何获取腾讯视频等九大视频网站的视频分享代码...
- oracle中那个日期怎么相减_oracle 日期相减
- 高通QPST Download使用方法
- 88E1111使用记录
- finalcut剪切快捷键_final cut pro怎么用快捷键把时间线上的素材移动到入点或剪辑点...
- CToolBar的使用总结(1)
- 布道微服务_11监控系统选型与常见方案
- Apache DolphinScheduler 是如何诞生的
- 海康威视录像机如何添加大华摄像头
- 计算机无法识别苹果6手机软件,电脑里安装的itunes不能识别我的苹果6sp… - Apple 社区...
- 新型冠状病毒全国疫情新浪腾讯网易API接口json