目录:
线程(thread)
查看主线程
当前最忙的N个线程
1 2 3 4
| thread -n 3 -i 1000 #列出1000ms内最忙的3个线程 "C1 CompilerThread0" [Internal] cpuUsage=1.63% deltaTime=3ms time=1170ms "arthas-command-execute" Id=23 cpuUsage=0.11% deltaTime=0ms time=401ms RUNNABLE "VM Periodic Task Thread" [Internal] cpuUsage=0.07% deltaTime=0ms time=584ms
|
- 没有线程ID,包含[Internal]表示为JVM内部线程,参考dashboard命令的介绍。
- cpuUsage为采样间隔时间内线程的CPU使用率,与dashboard命令的数据一致。
- deltaTime为采样间隔时间内线程的增量CPU时间,小于1ms时被取整显示为0ms。
- time 线程运行总CPU时间。
找出当前阻塞其他线程的线程
注意, 目前只支持找出synchronized关键字阻塞住的线程, 如果是java.util.concurrent.Lock, 目前还不支持。
查看置顶状态的线程
1
| thread -state WAItING|RUNNABLE|BLOCKED|TIMED_WAITING|TERMINATED
|
虚拟机信息(jvm)
Thread相关
- COUNT:JVM当前活跃的线程数
- DEAEMON-COUNt:JVM当前活跃的守护线程数
- PEAK-COUNT:从JVM启动开始曾经活着的最大线程数
- STARTED- COUNT:从JVM启动开始总共启动过的线程次数
- DEADLOCK-COUNT:JVM当前死锁的线程数
文件描述符相关
- MAX-FiLE-DESCRIPTOR-COUNT:JVM进程最大可以打开的文件描述符
- OPEN-FILE-DESCRIPTOR-COUNT:JVM当前打开的文件描述符数
日志(logger)
更新日志级别
1 2 3 4
| ##默认情况下 通过 SystemClassloader执行 logger --name ROOT --level debug|info|error ##war应用、springboot fat jar ,需要制定classloader logger -c 2a139ss --name ROOT --level debug
|
查看no appender 的日志
1
| logger --include-no-appender
|
类信息
查找类
1 2 3 4 5 6 7 8 9
| sc class_name # 详细信息: sc -d class_name # 正则搜索 sc -E regex # 输出成员变量 sc -d -f class_name # 变量遍历深度 sc -d -f -x 0 class_name
|
搜索类的方法信息
1 2 3 4 5 6
| sm class_name method_name
# 输出详细信息 sm -d class_name method_name # 正则搜索 sm -E regex
|
查看静态属性
1 2 3 4 5
| getstatic class_name field_name # 指定类加载器 getstatic -c 1324j103 class_name field_name # ognl表达式 getstatic class_name field_name'entrySet().iterator.{? #this.key=="a"}'
|
堆信息(heapdump)
1 2 3 4 5 6 7 8
| # dump到临时文件 heapdump
# 指定文件 heapdump /tmp/dump.hprof
# 只dump live对象 heapdump --live /tmp/dump.hprof
|
强制GC
获取对象
1 2 3 4 5 6 7 8
| vmtool --action getInstances --className java.lang.String --limit 10
# 指定加载器 vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext # 指定加载器 hashcode # hashcode 通过sc 查找类获得 vmtool --action getInstances -c 19469ea2 --className org.springframework.context.ApplicationContext
|
反编译类
1 2 3 4 5 6 7 8 9
| jad java.lang.String # 只显示源码 jad --source-only java.lang.String # 指定方法 jad java.lang.String toString # 不显示行号 jad java.lang.String --lineNumber false # 指定类加载器 jad -c hashcode java.lang.String
|
加载类
1
| classloader -c 1232131s --load class_name
|
编译文件
1 2 3 4 5
| mc /tmp/Test.java # 指定类加载器 mc -c xa1324 /tmp/Test.java # 输出目录 mc -d /tmp/output /tmp/A.java /tmp/B.java
|
热加载class
1 2 3 4 5 6 7 8 9
| # 通过sc查找需要修改的class的ClassLoader sc -d *OAuthClient |grep classLoaderHash # jad --source-only xxx.OAuthClient > /tmp/OAuthClient.java # 修改类文件 vim /tmp/OAuthClient.java # 重新编译 mc -d /tmp /tmp/OAuthClient.java # 再使用retransform命令重新加载新编译好的OAuthClient.class retransform -c 452c5c14 /tmp/OAuthClient.class
|
观察方法执行数据
可以观察:返回值、抛出异常、入参;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| # 一直观察方法执行 watch class_name method_name "{params,returnObj,throwExp}"
# 观察一次就自动退出 watch class_name method_name "{params,returnObj,throwExp}" -n 1
# 展开深度 watch class_name method_name "{params,returnObj,throwExp}" -x 2
# 调用前 watch class_name method_name "{params,returnObj}" -b
# 调用前、后 watch class_name method_name "{params,returnObj}" -b -s -n 2
# 增加条件表达式过滤、只有满足条件的才会响应 watch class_name method_name "{params[0],target}" "params[0]<0"
# 只有异常才会出发: -e watch class_name method_name "{params[0],throwExp}" -e -x 2
|
观察方法执行记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| # -n 就次数 tt -t class_name method_name -n 3 # 区分重载方法 tt -t *Test print params.length==1 # 指定参数 tt -t *Test print 'params[1] instanceof Integer' tt -t *Test print params[0].mobile=="13989838402"
# 筛选 tt -s 'methond.name=="primeFactors"' # 查看调用信息 tt -i 1003 # 重新调用 tt -i 1004 -p
|