关于arthas的一个比较有用的使用方式
arthas是阿里开源的一个非常好用的java诊断工具,提供了很多很好用的命令,这里讲一个最近使用到的
就是将arthas挂载上我们的springboot应用,然后调用其中的方法,这样能够在如果没加日志已经看不到函数返回时更方便的排查问题
首先举个例子,我们有个Controller
它的一个query方法是这样的1
2
3
4
5
public String query() {
return demoService.queryName("1");
}
而在这个demoService中它的实现是这样1
2
3
4
5
6
7public String queryName(String no) {
if ("1".equals(no)) {
return "no1";
} else {
return "no2";
}
}
假如现在Controller这的这个方法有点问题,那么我想确认下是不是demoService这个方法的实现有问题,或者说确定下它的返回值是否符合预期
那么我们就可以在应用启动后,运行arthas,找到这个应用的进程,进行挂载
然后执行1
vmtool --action getInstances --className com.nicksxs.spbdemo.service.DemoServiceImpl --express 'instances[0].queryName("1")'
先介绍下这个vmtool
命令
主要来说 vmtool 可以利用JVMTI接口,实现查询内存对象,强制 GC 等功能。
例如官方示例里的,我想把内存里的string对象捞一些出来看看存的是啥1
vmtool --action getInstances --className java.lang.String --limit 10
就可以这样,首先这个action就是指定要做的操作,支持的action 还包括1
2forceGc
interruptThread
等,那么对于 getInstances
就是从内存里捞出这个类的对象,然后是后面一部分--express
就是执行表达式,这里的表达式,instances[0].queryName("1")
其中 instances
就是前面从内存中获取的对象数组,因为这些是对象的非静态方法,那就需要从其中取一个来执行我们的方法
另外假如我们的场景里需要对比如返回结果做个json序列化
我们可以这样1
vmtool --action getInstances --className com.nicksxs.spbdemo.service.DemoServiceImpl --express '@com.alibaba.fastjson.JSON@toJSONString(instances[0].queryName("1"))'
这里为什么类开头跟方法开头要用 @
, 是因为对于类和静态方法的调用规则是这样,还有如果代码比较多,有可能默认的类加载器中没有加载这个JSON
类,那么就需要在参数中加上指定的classloader,
可以用sc命令来查找我们的目标类的类加载器,一般来说如果目标类是我们核心业务的,大概率也会有JSON这个类1
sc -d com.nicksxs.spbdemo.service.DemoServiceImpl
然后在上面命令中加上sc结果中的 classLoaderHash 的值,1
vmtool --action getInstances -c 18b4aac2 --className com.nicksxs.spbdemo.service.DemoServiceImpl --express '@com.alibaba.fastjson.JSON@toJSONString(instances[0].queryName("1"))'
这样就能正常执行了