使用约束
1、需要 jdk,如果部署的应用是jre 运行,需要上传jdk
2、热替换class 同debug 时热替换一样,不能新增方法和字段,否则替换失败。
3、执行arths 的 用户必须与 目标程序运行的用户相同,否则无法连接目标进程
执行
jdkpath/bin/java -jar /path/to/arthas-boot.jar
PS C:\Users\wangchangjin\Downloads\arthas-bin> java -jar .\arthas-boot.jar
[INFO] JAVA_HOME: D:\program\jdk\jdk8_64\jre
[INFO] arthas-boot version: 3.6.7
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 14256 org.jetbrains.jps.cmdline.Launcher
[2]: 2352
[3]: 15080 org.jetbrains.idea.maven.server.RemoteMavenServer36
[4]: 22684 com.example.demo.DemoApplication
4
[INFO] arthas home: C:\Users\wangchangjin\Downloads\arthas-bin
[INFO] Try to attach process 22684
[INFO] Attach process 22684 success.
[INFO] arthas-client connect 127.0.0.1 3658
,---. ,------. ,--------.,--. ,--. ,---. ,---.
/ O \ | .--. ''--. .--'| '--' | / O \ ' .-'
| .-. || '--'.' | | | .--. || .-. |`. `-.
| | | || |\ \ | | | | | || | | |.-' |
`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----'
wiki https://arthas.aliyun.com/doc
tutorials https://arthas.aliyun.com/doc/arthas-tutorials.html
version 3.6.7
main_class
pid 22684
time 2023-03-26 18:52:42
内存操作
查看类静态变量的值
[arthas@16048]$ getstatic com.example.demo.DemoApplication TEST
field: TEST
@String[TEST]
Affect(row-cnt:1) cost in 24 ms.
修改静态变量
final 修饰的静态变量无法修改
[arthas@22684]$ getstatic com.example.demo.DemoApplication TEST
field: TEST
@String[TEST]
Affect(row-cnt:1) cost in 25 ms.
[arthas@22684]$ ognl '#c=@com.example.demo.DemoApplication@class,#f=#c.getDeclaredField("TEST"),#f.setAccessible(true),#f.set(#c,"modify static private ")'
null
[arthas@22684]$ getstatic com.example.demo.DemoApplication TEST
field: TEST
@String[modify static private ]
Affect(row-cnt:1) cost in 5 ms.
[arthas@22684]$
查看私有属性的值
[arthas@1020]$ vmtool --action getInstances --className com.example.demo.DemoApplication --express 'instances[0].privateF'
@String[111]
修改私有属性
.
[arthas@1020]$ vmtool --action getInstances --className com.example.demo.DemoApplication --express '#val=instances[0],#val.privateF="222"'
vmtool error: By default, strict mode is true, not allowed to set object properties. Want to set object properties, execute `options strict false`
[arthas@1020]$ options strict false
NAME BEFORE-VALUE AFTER-VALUE
-----------------------------------
strict true false
[arthas@1020]$ vmtool --action getInstances --className com.example.demo.DemoApplication --express '#val=instances[0],#val.privateF="222"'
@String[222]
[arthas@1020]$ vmtool --action getInstances --className com.example.demo.DemoApplication --express 'instances[0].privateF'
@String[222]
[arthas@1020]$
获取类的实例调用并调用方法
[arthas@16048]$ vmtool --action getInstances --className com.example.demo.DemoTest
@DemoTest[][
@DemoTest[com.example.demo.DemoTest@4a37cea],
]
[arthas@16048]$ vmtool --action getInstances --className com.example.demo.DemoTest --express 'instances[0].getAge()'
@Integer[50]
class 替换
与debug比优点,不用重启,方便回退,省下不少时间,限制同debug,替换的class 不能新增方法
stramApi 的lamda 表达式也是算是方法
热替换class
[arthas@16048]$ retransform /DemoTest.class
retransform success, size: 1, classes:
com.example.demo.DemoTest
查看热替换列表
[arthas@16048]$ retransform -l
Id ClassName TransformCount LoaderHash LoaderClassName
1 com.example.dem 1 null null
o.DemoTest
还原热替换的class
[arthas@16048]$ retransform -d 1
[arthas@16048]$ retransform --classPattern com.example.demo.DemoTest
retransform success, size: 1, classes:
com.example.demo.DemoTest
时耗度量
监控方法调用时长
[arthas@21944]$ trace com.example.demo.DemoTest getAge
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 144 ms, listenerId: 1
`---ts=2023-03-26 17:23:33;thread_name=http-nio-8080-exec-1;id=1b;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@50305a
`---[0.5094ms] com.example.demo.DemoTest:getAge()
监控方法调用入参和返回值
[arthas@21944]$ watch com.example.demo.DemoApplication hello "{params,returnObj}" -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 2 , method count: 1) cost in 71 ms, listenerId: 5
method=com.example.demo.DemoApplication.hello location=AtExit
ts=2023-03-26 17:33:37; [cost=0.1492ms] result=@ArrayList[
@Object[][
@String[tom],
],
@String[hello,tom51],
]
-x 表示入参展开层数,默认是1
打印方法调用堆栈
[arthas@21944]$ stack com.example.demo.DemoTest getAge
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 50 ms, listenerId: 6
ts=2023-03-26 17:37:17;thread_name=http-nio-8080-exec-6;id=20;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@50305a
@com.example.demo.DemoTest.getAge()
at com.example.demo.DemoApplication.hello(DemoApplication.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:502)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:596)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:492)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
日志
查看日志appenders
[arthas@21944]$ logger
name ROOT
class ch.qos.logback.classic.Logger
classLoader sun.misc.Launcher$AppClassLoader@18b4aac2
classLoaderHash 18b4aac2
level INFO
effectiveLevel INFO
additivity true
codeSource file:/D:/program/maven_repo/ch/qos/logback/logback-classic/1.2.11/logback-classic-1.2.11.jar
appenders name CONSOLE
class ch.qos.logback.core.ConsoleAppender
classLoader sun.misc.Launcher$AppClassLoader@18b4aac2
classLoaderHash 18b4aac2
target System.out
更改级别
[arthas@21944]$ logger --name ROOT --level debug
Update logger level success.
参考
官方文档:https://arthas.aliyun.com/
OGNL 表达式官网:https://commons.apache.org/proper/commons-ognl/language-guide.html
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!