Arthas 使用(二) —— 应用场景
2024-09-03 17:15:58
1. ognl获取bean
SpringContextUtil,通常代码中会有类似这样的工具类用来获取 bean 实例
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
public static Object getBean(String beanName) {
return applicationContext.getBean(beanName);
}
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
}
UserController
@RestController
public class UserController {
private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);
@GetMapping("/user/{id}")
public User getUser(@PathVariable Integer id) {
if (null == id) {
throw new IllegalArgumentException("id can not be null");
}
if (id < 1) {
throw new IllegalArgumentException("id must be greater than 1");
}
return new User(id, "zhangsan");
}
}
使用 arthas 连接 spring 应用,执行如下操作:
查找全类名
sc *SpringContextUtil
查找类加载器
sc -d *SpringContextUtil | grep classLoaderHash
使用ognl表达式获取bean,并调用方法
> ognl -c 18b4aac2 '@com.soulballad.usage.arthasdemo.util.SpringContextUtil@getBean("userController").getUser(2)'
2. watch观测方法调用
# 查看 UserController 下所有方法的 参数、对象、返回值
watch com.soulballad.usage.arthasdemo.web.UserController * '{params,target,returnObj}'
watch 支持方法调用前、调用后、异常抛出等多个场景观测,同时还可以在第四个参数中使用条件进行过滤,比如:
watch com.soulballad.usage.arthasdemo.web.UserController * '{returnObj}' 'params[0]>10'
watch com.soulballad.usage.arthasdemo.web.UserController * '{returnObj}' '#cost>10'
3. 热更新
步骤:使用jad反编译 -> 修改文件 -> 使用mc重新编译修改后的文件->使用redefine加载重新编译后的类
上述 UserController 访问 user/0
,会出现如下错误:
There was an unexpected error (type=Internal Server Error, status=500).
id must be greater than 1
现对其进行热更新
反编译 UserController
# --source-only 只输出源码
jad --source-only com.soulballad.usage.arthasdemo.web.UserController > UserController.java
修改编译后的文件
package com.soulballad.usage.arthasdemo.web; import com.soulballad.usage.arthasdemo.model.User;
import com.soulballad.usage.arthasdemo.util.SpringContextUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController; @RestController
public class UserController {
private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class); @GetMapping(value={"/user/{id}"})
public User getUser(@PathVariable Integer id) {
if (null == id) {
throw new IllegalArgumentException("id can not be null");
}
if (id < 1) {
// throw new IllegalArgumentException("id must be greater than 1");
return new User(id, "lisi"+id);
}
return new User(id, "zhangsan");
}
}
重新编译
# 使用mc重新编译修改后的文件,这里需要使用 -c 指定类加载器
sc -d com.soulballad.usage.arthasdemo.web.UserController | grep classLoaderHash
mc -c 18b4aac2 UserController.java
编译完成会出现一个路径,这个路径就是编译后class文件的位置
使用redefine重新加载
# redefine 后面使用上一步的路径,需要将 \ 转成 /
redefine ../UserController.class
更新后结果
4. 更新日志级别
查找类加载器
sc -d *UserController | grep classLoaderHas
查看更新前日志级别
ognl -c 18b4aac2 '@com.soulballad.usage.arthasdemo.web.UserController@LOGGER'
更新日志级别为 DEBUG
ognl -c 18b4aac2 '@com.soulballad.usage.arthasdemo.web.UserController@LOGGER.setLevel(@ch.qos.logback.classic.Level@DEBUG)'
查看更新后日志级别
5. tt获取spring上下文
执行 tt
命令来记录 RequestMappingHandlerAdapter#invokeHandlerMethod
的请求
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod
然后访问 user/1
,arthas 会记录访问时间片(time fragment)
可以用 tt
命令的 -i
参数来指定index,并且用 -w
参数来执行ognl表达式来获取spring context:
tt -i 1000 -w 'target.getApplicationContext()'
可以从 applicationContext 中获取 bean,触发方法调用
tt -i 1000 -w 'target.getApplicationContext().getBean("userController").getUser(2)'
6. 链接
- Arthas: https://github.com/alibaba/arthas
- https://alibaba.github.io/arthas/tt.html
- https://alibaba.github.io/arthas/ognl.html
- https://alibaba.github.io/arthas/redefine.html
- https://alibaba.github.io/arthas/watch.html
最新文章
- ASP.NET Core 中文文档 第三章 原理(16).NET开放Web接口(OWIN)
- AVPlayer
- 项目vue2.0仿外卖APP(五)
- NXP恩智浦P89V52X2单片机破解P89C52X2BA芯片解密技术分享!
- http的header参数有关
- C#WebClient常见用法
- 【JVM学习笔记一】JVM内存分布
- 4.22 注入js需要加 addjavascriptinterface
- What is the Xcopy Command?:
- art.dialog 与 ajax 异步请求
- 改变Android按钮背景颜色的高效方法
- 利用Visual Studio寻找C#程序必要的运行库文件
- Linux Redis集群搭建与集群客户端实现(Python)
- 使用脚本监控windows服务的方法
- 写出优雅又地道的pythonic代码(转自网络)
- TP5整合 WorkerMan 以及 GatewayWorker
- Oracle学习DaySix(PL/SQL续)
- VC++全屏
- OAF日志使用总结
- java 学习网站