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

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

通过调用方法

ThreadMXBean tmbean = ManagementFactory.getThreadMXBean();

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

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

1. getThreadCount()

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

[cpp] view plaincopy print?
  1. PerfCounter*  ThreadService::_total_threads_count = NULL;
  2. PerfVariable* ThreadService::_live_threads_count = NULL;
  3. PerfVariable* ThreadService::_peak_threads_count = NULL;
  4. PerfVariable* ThreadService::_daemon_threads_count = NULL;
  5. volatile int ThreadService::_exiting_threads_count = 0;
  6. volatile int ThreadService::_exiting_daemon_threads_count = 0;

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

2. getAllThreadIds()

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

[cpp] view plaincopy print?
  1. ThreadsListEnumerator::ThreadsListEnumerator(Thread* cur_thread,
  2. bool include_jvmti_agent_threads,
  3. bool include_jni_attaching_threads) {
  4. assert(cur_thread == Thread::current(), "Check current thread");
  5. int init_size = ThreadService::get_live_thread_count();
  6. _threads_array = new GrowableArray<instanceHandle>(init_size);
  7. MutexLockerEx ml(Threads_lock);
  8. for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) {
  9. // skips JavaThreads in the process of exiting
  10. // and also skips VM internal JavaThreads
  11. // Threads in _thread_new or _thread_new_trans state are included.
  12. // i.e. threads have been started but not yet running.
  13. if (jt->threadObj() == NULL   ||
  14. jt->is_exiting() ||
  15. !java_lang_Thread::is_alive(jt->threadObj())   ||
  16. jt->is_hidden_from_external_view()) {
  17. continue;
  18. }
  19. // skip agent threads
  20. if (!include_jvmti_agent_threads && jt->is_jvmti_agent_thread()) {
  21. continue;
  22. }
  23. // skip jni threads in the process of attaching
  24. if (!include_jni_attaching_threads && jt->is_attaching()) {
  25. continue;
  26. }
  27. instanceHandle h(cur_thread, (instanceOop) jt->threadObj());
  28. _threads_array->append(h);
  29. }
  30. }

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

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

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

[cpp] view plaincopy print?
  1. // Obtain thread dumps and thread snapshot information
  2. VM_ThreadDump op(dump_result,
  3. thread_handle_array,
  4. num_threads,
  5. max_depth, /* stack depth */
  6. with_locked_monitors,
  7. with_locked_synchronizers);
  8. 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[]  可以得到具体的类,锁的数量和信息

Java多线程--使用ThreadMXBean 打出堆栈信息相关推荐

  1. JVM源码系列:ThreadMXBean 打出堆栈信息原理分析

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

  2. java.lang.NullPointerException: null无堆栈信息

    今天遇到个java.lang.NullPointerException: null,发现没有堆栈信息,无法定位.看了下代码,按道理是会打印堆栈的啊. try {... } catch(Throwabl ...

  3. 使用jstack查看某个Java进程内的线程堆栈信息

    本文来说下如何使用jstack来查看堆栈信息 文章目录 概述 概述

  4. java string转elements_Java异常堆栈信息转String

    平时使用e.getMessage()或e.printStackTrace(); 第一种报异常时要throw new RuntimeException("异常"),只能得到异常2字. ...

  5. Win Linux Java 项目堆栈信息调试教程

    使用堆栈信息排查系统性能问题,多线程程序调优(因为这类问题往往都不会输出日志或日志输出定位代码排查的范围太大),堆栈信息对这类问题定位速度快而精准. 查询堆栈信息全文涉及到的指令 线程状态相关 常见到 ...

  6. jstack-查看Java进程的线程堆栈信息,锁定高消耗资源代码

    jstack主要用来查看某个Java进程内的线程堆栈信息.语法格式如下: jstack [option] pid jstack [option] executable core jstack [opt ...

  7. 获取java异常堆栈信息_Java 实例 - 获取异常的堆栈信息

    全屏 Java 实例 - 获取异常的堆栈信息 以下实例演示了使用异常类的 printStack() 方法来获取堆栈信息: Main.java 文件public class Main{ public s ...

  8. docker 导出堆栈信息.hprof_JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用...

    现实企业级Java应用开发.维护中,有时候我们会碰到下面这些问题: OutOfMemoryError,内存不足 内存泄露 线程死锁 锁争用(Lock Contention) Java进程消耗CPU过高 ...

  9. 浅谈Java多线程机制

    浅谈Java多线程机制 (-----文中重点信息将用红色字体凸显-----) 一.话题导入 在开始简述Java多线程机制之前,我不得不吐槽一下我国糟糕的IT界技术分享氛围和不给力的互联网技术解答深度. ...

最新文章

  1. iOS开发系列--C语言之存储方式和作用域
  2. 数学问题的解题方法(模板)
  3. 文巾解题 LCP 11. 期望个数统计
  4. Android的Intent你知道多少?
  5. 长白山特色产品谋定农民丰收节交易会 吉林蛟河农商互联
  6. 私募公司完成对戴尔软件的收购 SonicWall与Quest将分别独立
  7. [转]ASP.NET 状态服务 及 session丢失问题解决方案总结
  8. jqgrid 编辑状态获取该单元格的元素的id 和操作该元素
  9. 关于TCP或FTP异常断开的处理方法总结
  10. 《java就业培训教程》读书笔记
  11. 台式计算机颜色如何矫正,台式机怎么颜色校正操作教程
  12. qq音乐网络异常获取音乐失败_qq音乐网络异常获取音频失败怎么办
  13. Oracle之现有表上建新表、操作符、字符函数
  14. 终于离职了,千万别在工作交接上翻车!
  15. android js 双指事件,移动端touch事件--点击、双指与拖拽
  16. 英语常见缩写,职业,公司
  17. #踩过的坑# 企业微信被封了怎么办?
  18. Armbian (jammy) 上安装 Docker
  19. AD20使用及PCB设计的学习
  20. 关于DOCX XML

热门文章

  1. 关于哨兵2号数据辐射定标
  2. UBC文学院的计算机科学,加拿大ubc本科留学申请,性价比超高哦!
  3. IBM 550安装IBM 3580磁带机
  4. 如何进行有效的性能测试
  5. 大专的软件测试很难找工作,大专一毕业就从事软件测试工作好吗
  6. 拉普拉斯金字塔融合原理公式
  7. 【单片机毕业设计】【mcuclub-108】衣柜除湿照明 | 智能衣柜 | 智能储物柜 | 衣柜环境监测 | 多功能衣柜【仿真设计】
  8. 【Linux入门】tldr:man手册的极佳替代
  9. java培训班教程视频最新尚硅谷Java培训全套教程
  10. 连连看算法 Unity版