这是我参与更文挑战的第5天,活动详情查看: 更文挑战
本文内容基于arthas 3.5.1 版本,介绍系统命令thread,jvm的使用及实现。
一.thread命令
查看当前线程信息,查看线程的堆栈
| 参数名称 | 参数缩写 | 参数说明 | 必填项 |
|---|---|---|---|
| id | 线程id | 可选 | |
| --all | 显示所有线程信息 | 可选 | |
| --top-n-threads | -n | 指定最忙的前N个线程并打印堆栈 | 可选 |
| --include-blocking-thread | -b | 找出当前阻塞其他线程的线程 | 可选 |
| --sample-interval | -i | 指定cpu使用率统计的采样间隔,单位为毫秒,默认值为200 | 可选 |
| --state | 按线程状态过滤,不区分大小写,可选项:NEW, RUNNABLE, TIMED_WAITING, WAITING, BLOCKED, TERMINATED | 可选 | |
| --lockedMonitors | 找出线程信息中带有lockedMonitors标识的,默认为false,可直接用thread -b | 可选 | |
| --lockedSynchronizers | 找出线程信息中带有lockedSynchronizers标识的,默认为false | 可选 |
文件位于com.taobao.arthas.core.command.monitor200.ThreadCommand.java。
如上图所示。当id参数存在时,执行processThread(process),查找指定id的thread信息。
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean()获取线程信息
ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(new long[]{id}, lockedMonitors, lockedSynchronizers);lockedMonitors和lockedSynchronizers默认均为false。
当参数topNBusy不为null时,即执行thread -n的时候,执行processTopBusyThreads(process),查找最忙的前N个线程并打印堆栈。
threadSampler.sample获取所有线程采样信息并且按照时间排序,只要截取列表前n个就是thread -n的内容。
当findMostBlockingThread为true,即执行thread -b的时候,进入分支执行processBlockingThread(process)找出当前阻塞其他线程的线程。
ThreadUtil.findMostBlockingLock()找出被阻塞的线程信息。
threadMXBean.dumpAllThreads(threadMXBean.isObjectMonitorUsageSupported(), threadMXBean.isSynchronizerUsageSupported())找出阻塞线程
isObjectMonitorUsageSupported()测试 Java 虚拟机是否支持使用对象监视器的监视。
isSynchronizerUsageSupported()测试 Java 虚拟机是否支持使用 可拥有同步器的监视。
最后,processAllThreads(process)获取所有线程,若有参数--state,则循环过滤出符合条件的线程。
ThreadSampler 线程的cpu取样器,用于统计线程的cpu使用情况。
通过java.lang.management.ThreadMXBean#getThreadCpuTime()及sun.management.HotspotThreadMBean#getInternalThreadCpuTimes()获取所有线程的调用时间。
将第一次的结果保存在一个HashMap中。当通过pause(long mills)方法即Thread.sleep(mills)睡眠等待一段时间后,在ThreadCommand中默认睡眠等待时间为2000ms。再次统计线程的cpu时间,与之前第一次的cpu时间比较,线程CPU使用率 = 线程增量CPU时间 / 采样间隔时间 * 100%获得cpu使用率。
二.jvm命令
查看当前JVM信息
文件位于com.taobao.arthas.core.command.monitor200.JvmCommand.java。
执行命令会打印出很多相关信息,通过JMX做jvm的监控。
使用ManagementFactory获取不同的MXBean,以下为获取内容项的代码。
addRuntimeInfo(jvmModel) 获取当前 JVM 的信息,包括 JVM 参数和 JVM 相关的系统参数。
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean()
| 名称 | 代码 |
|---|---|
| MACHINE-NAME | runtimeMXBean.getName() |
| JVM-START-TIME | runtimeMXBean.getStartTime() |
| MANAGEMENT-SPEC-VERSION | runtimeMXBean.getManagementSpecVersion() |
| SPEC-NAME | runtimeMXBean.getSpecName() |
| SPEC-VENDOR | runtimeMXBean.getSpecVendor() |
| SPEC-VERSION | runtimeMXBean.getSpecVersion() |
| VM-NAME | runtimeMXBean.getVmName() |
| VM-VENDOR | runtimeMXBean.getVmVendor() |
| VM-VERSION | runtimeMXBean.getVmVersion() |
| INPUT-ARGUMENTS | runtimeMXBean.getInputArguments() |
| CLASS-PATH | runtimeMXBean.getClassPath() |
| BOOT-CLASS-PATH | runtimeMXBean.getBootClassPath() 低于jdk9会报错不支持 |
| LIBRARY-PATH | runtimeMXBean.getLibraryPath() |
addClassLoading(jvmModel) 获取 JVM 类加载情况。
ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean()
| 名称 | 代码 |
|---|---|
| LOADED-CLASS-COUNT | classLoadingMXBean.getLoadedClassCount() |
| TOTAL-LOADED-CLASS-COUNT | classLoadingMXBean.getTotalLoadedClassCount() |
| UNLOADED-CLASS-COUNT | classLoadingMXBean.getUnloadedClassCount() |
| IS-VERBOSE | classLoadingMXBean.isVerbose() |
addCompilation(jvmModel) 获取 JVM 编译情况
CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean()
| 名称 | 代码 |
|---|---|
| NAME | compilationMXBean.getName() |
| TOTAL-COMPILE-TIME | compilationMXBean.getTotalCompilationTime() 单位ms |
addGarbageCollectors(jvmModel) 获取 JVM 垃圾收集器的情况。
Collection<GarbageCollectorMXBean> garbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans()
addMemoryManagers(jvmModel)
Collection<MemoryManagerMXBean> memoryManagerMXBeans = ManagementFactory.getMemoryManagerMXBeans()
addMemory(jvmModel)获取当前 JVM 的内存使用,包括堆内存和非堆内存。
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean()
addOperatingSystem(jvmModel)获取操作系统相关的信息
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean()
| 名称 | 代码 |
|---|---|
| OS | operatingSystemMXBean.getName() |
| ARCH | operatingSystemMXBean.getArch() |
| PROCESSORS-COUNT | operatingSystemMXBean.getAvailableProcessors() |
| LOAD-AVERAGE | operatingSystemMXBean.getSystemLoadAverage() |
| VERSION | operatingSystemMXBean.getVersion() |
addThread(jvmModel) 获取 JVM 线程使用情况。
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean()
| 名称 | 代码 |
|---|---|
| COUNT | threadMXBean.getThreadCount() 线程数 |
| DAEMON-COUNT | threadMXBean.getDaemonThreadCount()守护线程数 |
| PEAK-COUNT | threadMXBean.getPeakThreadCount() 峰值线程数 |
| STARTED-COUNT | threadMXBean.getTotalStartedThreadCount() 已启动的线程的总数 |
| DEADLOCK-COUNT | getDeadlockedThreadsCount(threadMXBean) 死锁线程数 |
addFileDescriptor(jvmModel)
| 名称 | 代码 |
|---|---|
| MAX-FILE-DESCRIPTOR-COUNT | OperatingSystemMXBean.class.getDeclaredMethod("getMaxFileDescriptorCount") |
| OPEN-FILE-DESCRIPTOR-COUNT | OperatingSystemMXBean.class.getDeclaredMethod("getOpenFileDescriptorCount") |