arthas 解决了哪些问题?看看官方的回答
这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
是否有一个全局视角来查看系统的运行状况?
有什么办法可以监控到JVM的实时运行状态?
怎么快速定位应用的热点,生成火焰图?
怎样直接从JVM内查找某个类的实例
案例
线程相关
//启动方式
//java -Xms27M -Xmx27M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGC -XX:+PrintGCDetails BlockTest
//参数不怎么了解的可以看下jvm篇
public class BlockTest {
public static void main(String[] args) throws Exception {
CountDownLatch latch = new CountDownLatch(2);
Object o1 = new Object();
Object o2 = new Object();
Thread t1 = new Thread(() -> {
synchronized (o1) {
System.out.println("t1 o1");
synchronized (o2){
System.out.println("t1 o2");
}
}
latch.countDown();
});
Thread t2 = new Thread(()->{
synchronized (o2){
System.out.println("t2 o2");
synchronized (o1){
System.out.println("t2 o1");
}
}
latch.countDown();
});
t1.start();
t2.start();
latch.await();
}
}
内存相关
// 启动命令 nohup java -Xms27M -Xmx27M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGC -XX:+PrintGCDetails MemoryTest 2>&1 &
public class MemoryTest {
public static List list = new LinkedList();
public static void main(String[] args) throws InterruptedException {
while(true){
list.add(new MemoryObj("1",1, new int[]{1}));
Thread.sleep(10);
}
}
static class MemoryObj{
private String str;
private Integer integer;
private int[] arr;
public MemoryObj(String str, Integer integer, int[] arr) {
this.str = str;
this.integer = integer;
this.arr = arr;
}
}
}
官方提供的SpringBoot
# 访问的时候比较慢
# 也可以直接在官方提供的虚拟机上操作
# https://arthas.aliyun.com/doc/arthas-tutorials.html?language=cn&id=arthas-advanced
wget https://github.com/hengyunabc/spring-boot-inside/raw/master/demo-arthas-spring-boot/demo-arthas-spring-boot.jar
java -jar demo-arthas-spring-boot.jar
操作
下载arthas-boot.jar
https://github.com/alibaba/arthas/releases
启动
java -jar arthas-boot.jar --target-ip 0.0.0.0 --telnet-port 9998 --http-port 9999
# 自动获取java程序(类似jps命令),然后排号,使用者输入对应的需要可进行监控
--target-ip 指定外部访问ip,默认未127.0.0.1
--use-version 3.1.0 指定使用版本
--telnet-port 9999 监听telnet端口
--http-port 监听http端口
-v 打印运行时详情
命令
dashboard 列出系统中线程、内存、os等线管信息
列说明
ID: Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应。
NAME: 线程名
GROUP: 线程组名
PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高
STATE: 线程的状态
CPU%: 线程的cpu使用率。比如采样间隔1000ms,某个线程的增量cpu时间为100ms,则cpu使用率=100/1000=10%
DELTA_TIME: 上次采样之后线程运行增量CPU时间,数据格式为秒
TIME: 线程运行总CPU时间,数据格式为分:秒
INTERRUPTED: 线程当前的中断位状态
DAEMON: 是否是daemon线程
thread 查看当前线程信息,查看线程的堆栈
thread -n 3 : 打印出前几个最忙的线程
thread -b : 查看程序中被阻塞的线程(线程状态为Blocked状态)
thread all :查看进程中所有的线程
thread tid :查看具体线程堆栈信息
thread -i ms : 指定特定时间采样,毫秒
thread --state threadstate : 指定线程状态查找列表
thread -n 3 -i 5000 :查看5秒内的CPU使用率top n线程栈
id为-1的线程为JVM内部线程
JIT编译线程: 如 C1 CompilerThread0, C2 CompilerThread0
GC线程: 如GC Thread0, G1 Young RemSet Sampling
其它内部线程: 如VM Periodic Task Thread, VM Thread, Service Thread
JVM 查看当前JVM信息
RUNTIME 运行信息
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MACHINE-NAME 21058@worker2
JVM-START-TIME 2022-01-04 14:34:22
MANAGEMENT-SPEC-VERSION 1.2
SPEC-NAME Java Virtual Machine Specification
SPEC-VENDOR Oracle Corporation
SPEC-VERSION 1.8
VM-NAME Java HotSpot(TM) 64-Bit Server VM
VM-VENDOR Oracle Corporation
VM-VERSION 25.221-b11
INPUT-ARGUMENTS []
CLASS-PATH .:/home/jdk1.8.0_221/lib/dt.jar:/home/jdk1.8.0_221/lib/tools.jar
BOOT-CLASS-PATH /home/jdk1.8.0_221/jre/lib/resources.jar:/home/jdk1.8.0_221/jre/lib/rt.jar:/home/jdk1.8.0_221/jre/lib/sunrsasign.jar:/home/jdk1.8.0_
221/jre/lib/jsse.jar:/home/jdk1.8.0_221/jre/lib/jce.jar:/home/jdk1.8.0_221/jre/lib/charsets.jar:/home/jdk1.8.0_221/jre/lib/jfr.jar:/
home/jdk1.8.0_221/jre/classes
LIBRARY-PATH /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CLASS-LOADING 类加载
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
LOADED-CLASS-COUNT 3500
TOTAL-LOADED-CLASS-COUNT 3500
UNLOADED-CLASS-COUNT 0
IS-VERBOSE false
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
COMPILATION 虚拟机
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NAME HotSpot 64-Bit Tiered Compilers
TOTAL-COMPILE-TIME 2517
[time (ms)]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GARBAGE-COLLECTORS 垃圾回收器
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PS Scavenge name : PS Scavenge
[count/time (ms)] collectionCount : 1
collectionTime : 18
PS MarkSweep name : PS MarkSweep
[count/time (ms)] collectionCount : 0
collectionTime : 0
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MEMORY-MANAGERS 内存管理
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CodeCacheManager Code Cache
Metaspace Manager Metaspace
Compressed Class Space
PS Scavenge PS Eden Space
PS Survivor Space
PS MarkSweep PS Eden Space
PS Survivor Space
PS Old Gen
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MEMORY 内存
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HEAP-MEMORY-USAGE init : 262144000(250.0 MiB)
[memory in bytes] used : 53054408(50.6 MiB)
committed : 251658240(240.0 MiB)
max : 3702521856(3.4 GiB)
NO-HEAP-MEMORY-USAGE init : 2555904(2.4 MiB)
[memory in bytes] used : 29251568(27.9 MiB)
committed : 29949952(28.6 MiB)
max : -1(-1 B)
PENDING-FINALIZE-COUNT 0
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OPERATING-SYSTEM 操作系统
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OS Linux
ARCH amd64
PROCESSORS-COUNT 8
LOAD-AVERAGE 4.22
VERSION 3.10.0-1127.13.1.el7.x86_64
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
THREAD 线程
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
COUNT 18
DAEMON-COUNT 13
PEAK-COUNT 19
STARTED-COUNT 22
DEADLOCK-COUNT 0
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
FILE-DESCRIPTOR 文件描述
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MAX-FILE-DESCRIPTOR-COUNT 65535
OPEN-FILE-DESCRIPTOR-COUNT 174
THREAD相关
COUNT: JVM当前活跃的线程数
DAEMON-COUNT: JVM当前活跃的守护线程数
PEAK-COUNT: 从JVM启动开始曾经活着的最大线程数
STARTED-COUNT: 从JVM启动开始总共启动过的线程次数
DEADLOCK-COUNT: JVM当前死锁的线程数
文件描述符相关
MAX-FILE-DESCRIPTOR-COUNT:JVM进程最大可以打开的文件描述符数
OPEN-FILE-DESCRIPTOR-COUNT:JVM当前打开的文件描述符数
sysprop 系统属性
KEY VALUE
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
awt.toolkit sun.awt.X11.XToolkit
file.encoding.pkg sun.io
java.specification.version 1.8
sun.cpu.isalist
sun.jnu.encoding UTF-8
java.class.path .:/home/jdk1.8.0_221/lib/dt.jar:/home/jdk1.8.0_221/lib/tools.jar
java.vm.vendor Oracle Corporation
sun.arch.data.model 64
java.vendor.url http://java.oracle.com/
user.timezone Asia/Shanghai
os.name Linux
java.vm.specification.version 1.8
user.country CN
sun.java.launcher SUN_STANDARD
sun.boot.library.path /home/jdk1.8.0_221/jre/lib/amd64
sun.java.command CpuTest
sun.cpu.endian little
user.home /root
user.language zh
java.specification.vendor Oracle Corporation
java.home /home/jdk1.8.0_221/jre
file.separator /
line.separator
java.vm.specification.vendor Oracle Corporation
java.specification.name Java Platform API Specification
java.awt.graphicsenv sun.awt.X11GraphicsEnvironment
sun.boot.class.path /home/jdk1.8.0_221/jre/lib/resources.jar:/home/jdk1.8.0_221/jre/lib/rt.jar:/home/jdk1.8.0_221/jre/lib/sunrsasign.jar:/home/jdk1.8.0_221/jre/lib/jsse
.jar:/home/jdk1.8.0_221/jre/lib/jce.jar:/home/jdk1.8.0_221/jre/lib/charsets.jar:/home/jdk1.8.0_221/jre/lib/jfr.jar:/home/jdk1.8.0_221/jre/classes
sun.management.compiler HotSpot 64-Bit Tiered Compilers
java.runtime.version 1.8.0_221-b11
user.name root
path.separator :
os.version 3.10.0-1127.13.1.el7.x86_64
java.endorsed.dirs /home/jdk1.8.0_221/jre/lib/endorsed
java.runtime.name Java(TM) SE Runtime Environment
file.encoding UTF-8
sun.nio.ch.bugLevel
java.vm.name Java HotSpot(TM) 64-Bit Server VM
java.vendor.url.bug http://bugreport.sun.com/bugreport/
java.io.tmpdir /tmp
java.version 1.8.0_221
user.dir /opt/arthas
os.arch amd64
java.vm.specification.name Java Virtual Machine Specification
java.awt.printerjob sun.print.PSPrinterJob
sun.os.patch.level unknown
java.library.path /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.vm.info mixed mode
java.vendor Oracle Corporation
java.vm.version 25.221-b11
java.ext.dirs /home/jdk1.8.0_221/jre/lib/ext:/usr/java/packages/lib/ext
sun.io.unicode.encoding UnicodeLittle
java.class.version 52.0
sysenv
环境属性
KEY VALUE
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PATH /home/jdk1.8.0_221/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/rocketmq4.7/bin:/opt/mysql5.7/bin:/root/bin
HISTCONTROL ignoredups
HISTSIZE 1000
JAVA_HOME /home/jdk1.8.0_221
TERM xterm
LANG zh_CN.UTF-8
XDG_SESSION_ID 761
SELINUX_LEVEL_REQUESTED
SELINUX_ROLE_REQUESTED
ROCKETMQ_HOME /opt/rocketmq4.7
MAIL /var/spool/mail/root
LOGNAME root
PWD /opt/arthas
_ /usr/bin/nohup
LESSOPEN ||/usr/bin/lesspipe.sh %s
SHELL /bin/bash
SELINUX_USE_CURRENT_RANGE
SSH_TTY /dev/pts/3
SSH_CLIENT 172.16.193.6 12543 22
OLDPWD /root
USER root
CLASSPATH .:/home/jdk1.8.0_221/lib/dt.jar:/home/jdk1.8.0_221/lib/tools.jar
SSH_CONNECTION 172.16.193.6 12543 172.16.14.108 22
HOSTNAME worker2
XDG_RUNTIME_DIR /run/user/0
LS_COLORS rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34
;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz
=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=
01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;3
1:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.
tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mp
eg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=
01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:
*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.m
pc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
HOME /root
SHLVL 1
vmoption 参数
KEY VALUE ORIGIN WRITEABLE
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HeapDumpBeforeFullGC false DEFAULT true
HeapDumpAfterFullGC false DEFAULT true
HeapDumpOnOutOfMemoryError false DEFAULT true
HeapDumpPath DEFAULT true
CMSAbortablePrecleanWaitMillis 100 DEFAULT true
CMSWaitDuration 2000 DEFAULT true
CMSTriggerInterval -1 DEFAULT true
PrintGC false DEFAULT true
PrintGCDetails false DEFAULT true
PrintGCDateStamps false DEFAULT true
PrintGCTimeStamps false DEFAULT true
PrintGCID false DEFAULT true
PrintClassHistogramBeforeFullGC false DEFAULT true
PrintClassHistogramAfterFullGC false DEFAULT true
PrintClassHistogram false DEFAULT true
MinHeapFreeRatio 0 DEFAULT true
MaxHeapFreeRatio 100 DEFAULT true
PrintConcurrentLocks false DEFAULT true
UnlockCommercialFeatures false DEFAULT true
perfcounter 性能监控
perfcounter -d 打印更详细信息
mbean 查看或监控 Mbean 的属性信息
每隔一秒打印一次Threading信息
mbean -i 1000 java.lang:type=Threading *Count
打印出Runtime信息(运行时信息,如运行时参数)
mbean java.lang:type=Runtime
java.lang:type=MemoryPool,name=Metaspace
java.lang:type=MemoryPool,name=PS Old Gen
java.lang:type=GarbageCollector,name=PS Scavenge
java.lang:type=MemoryPool,name=PS Eden Space
JMImplementation:type=MBeanServerDelegate
java.lang:type=Runtime
java.lang:type=Threading
java.lang:type=OperatingSystem
java.lang:type=MemoryPool,name=Code Cache
java.nio:type=BufferPool,name=direct
java.lang:type=Compilation
java.lang:type=MemoryManager,name=CodeCacheManager
java.lang:type=MemoryPool,name=Compressed Class Space
java.lang:type=Memory
java.nio:type=BufferPool,name=mapped
java.util.logging:type=Logging
java.lang:type=MemoryPool,name=PS Survivor Space
java.lang:type=ClassLoading
java.lang:type=MemoryManager,name=Metaspace Manager
com.sun.management:type=DiagnosticCommand
java.lang:type=GarbageCollector,name=PS MarkSweep
com.sun.management:type=HotSpotDiagnostic
getstatic 查看类的静态属性
sc 查看JVM已加载的类信息
sc -d -f BlockTest
-d 打印详细信息
-f 打印类得Field
sm 查看已加载类的方法信息
和sc使用方法一致
dump 已加载类的 bytecode
dump -d ./temp BlockTest
-d 指定导出的路径
heapdump 导出堆
heapdump ./temp/block.hprof
vmtool 查询内存对象,强制GC
vmtool --action getInstances --classLoaderClass sun.misc.Launcher$ExtClassLoader --className java.util.concurrent.CountDownLatch --limit 100
--limit 100 指定返回条数
vmtool --action getInstances --classLoaderClass sun.misc.Launcher$AppClassLoader --className BlockTest
--classLoaderClass 指定类加载器
vmtool --action forceGc 强制GC
jad 反编译
jad --source-only BlockTest main
--source-only 只展示自己的代码
--lineNumber false 隐藏行号
--main 指定类的方法
classloader 查看类加载器
classloader
-t 列出继承树
-l 详情
mc 内存编译器,编译.java文件生成.class
mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp
redefine 热替换
redefine /tmp/com/example/demo/arthas/user/UserController.class
热替换流程
1、找到对应的类进行反编译
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
2、修改class文件
3、找到对应class文件类加载器哈希code
sc -d *UserController | grep classLoaderHash
classLoaderHash 728938a9
4、重新编译目标类
mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp
/tmp/com/example/demo/arthas/user/UserController.class
5、使用redefine命令重新加载新编译好的UserController.class
redefine /tmp/com/example/demo/arthas/user/UserController.class
6、再次验证对应的代码是否已经更改
watch 函数执行数据观测(捕获异常)
watch com.example.demo.arthas.user.UserController * '{params, throwExp}' -x 2
-x 2 展开
watch com.example.demo.arthas.user.UserController * "{params[0],throwExp}" -e
-e 只捕获抛出异常的请求
动态更改应用日志级别
1、查询类加载器哈希code
sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash
classLoaderHash 728938a9
2、用ognl获取logger
ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'
3、单独设置UserController的日志级别
ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger.setLevel(@ch.qos.logback.classic.Level@DEBUG)'
4、再次获取
ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'
5、设置全局level等级
ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@org.slf4j.LoggerFactory@getLogger("root").setLevel(@ch.qos.logback.classic.Level@DEBUG)'
-----------logger冲突排查-------------------
6、获取实际的logger配置文件
ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '#map1=@org.slf4j.LoggerFactory@getLogger("root").loggerContext.objectMap, #map1.get("CONFIGURATION_WATCH_LIST")'
7、查找可能存在的logger配置文件
classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback-spring.xml
8、可以尝试加载容易冲突的文件
classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r logback.xml
classloader --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -r log4j.properties
tt 记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
获取请求
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod
获取spring应用上下文
tt -i 1000 -w 'target.getApplicationContext()'
获取spring中bean并调用方法
tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()'
trace方法内部调用路径,并输出方法路径上的每个节点上耗时
如访问接口401时
trace javax.servlet.Filter *
+---[0.162227ms] javax.servlet.FilterChain:doFilter() #99
| | | | | `---[0.093406ms] com.example.demo.arthas.AdminFilterConfig$AdminFilter:doFilter()
| | | | | `---[0.049584ms] javax.servlet.http.HttpServletResponse:sendError() #38
通过stack获取调用栈
stack javax.servlet.http.HttpServletResponse sendError 'params[0]==401'
和打印异常调用栈一样的清晰
profiler 应用热点火焰图
开启
profiler start
查看统计数量
profiler getSamples
查看状态及统计的时间
profiler status
结束并生成html页面
profiler stop --format html
生成文件位置
profiler output file: /opt/arthas/app/arthas-output/20220224-175834.html
访问
http://localhost:${http-port}/arthas-output