Arthas是一个非常牛B的东西,我非常喜欢用,特别是在定义线上问题的时候,牛逼大发!
非常建议所有Java玩家都去学习一下
先说结论,lambda表达式的追踪,大概格式如下:
假设你的lambda表达式写在函数Demo
类的test
方法里面,正常trace
是:trace Demo test
。但如果你的test
方法,里面有lambda表达式,你想要trace
里面的内容,你大概需要这么改:trace Demo lambda$test$0
。
我也不是很理解那个0是啥意思,我猜测是
test
方法内第几个lambda表达式的意思,然后是从0开始
如果你看了结论之后,没办法解决你的问题,那就往下看,仔细看完吧。
RT,我在我的线上环境中遇到了一个问题,问题其实很简单,一眼能看出来。
但重点是,我想使用Arthas去定位线上问题的时候,发现一个很尴尬的点,那就是,简单的trace
,无法trace
到匿名函数里面的执行情况。
大概的伪代码如下:
public void test() {
// 从数据库获取数据
List<MyReport> reportList = baseMapper.list();
// 数据遍历
reportList.foreach(p -> {
// 在这里面做一系列的运算,代码800行
// 但是在这里面出了问题
doSomething();
});
}
按照上面这种伪代码,如果你trace Demo test
的话,正常来说,它的输出打印类似下面:
`---ts=2023-12-26 11:17:20;thread_name=http-nio-8300-exec-15;id=52;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@5b202a3a
`---[1699.530527ms] vip.xiaonuo.kitchen.modular.report.service.impl.ReportOrderAnalysisServiceImpl$$EnhancerBySpringCGLIB$$c02dbff3:test() [throws Exception]
| +---[0.00% 0.017071ms ] java.util.ArrayList:<init>() #18
| +---[0.02% 0.258435ms ] java.util.List:forEach() #19 [throws
| `---throw:java.lang.ArithmeticException #-1 [null]
`---throw:java.lang.ArithmeticException #-1 [null]
但显然,这个没办法满足我的要求,我想要知道,在foreach
里面,到底是哪一步处理问题。
于是,我就网上百度:Arthas如何trace 【匿名函数/Lambda表达式/函数式接口】。可惜,都没有理想的方案,甚至说,没有一个人给出了答案。那能怎么办,我只能去看官网了。
话说回来,其实官网也并没有给出一个答案来,不过,在官方github上,我得到了一些灵感。官方说:
总结一下就是:trace本身只能拿到当前method的字节码,所以它只能trace当前method里的 invokevirtual
关键词:method字节码!
所以,我就想着,是否从字节码入手。我印象中,class的字节码,是有【方法】组的
解决只需要2步。
首先,需要在Idea安装一个字节码查看插件,jclasslib bytecode viewer
然后,确保自己的代码已经编译完成的前提下,打开需要查看的Java代码文件
再点击菜单栏的view => show bytecode with Jclasslib
即可打开字节码窗口,接着你会得到如下图所示的文件:
点击方法,你就会查看到,匿名函数在字节码下的命名了。如下:
比如我上图圈红处,我的文件中有一个getOrderAnalysisInfo
方法,并且在里面使用了foreach
,声明了唯一的lambda表达式,所以,可以确定lambda$getOrderAnalysisInfo$0
就是我要的真正的函数。
这里就不多解释了,把你的trace Demo test
,改成trace Demo lambda$test$0
就好了
当然,我们已经知道了字节码命名风格之后,可以不用安装上面说的字节码插件了,就按照这种命名方式trace
即可。
感谢百度大佬【作者:程序员子悠】的文章《IDEA 字节码学习查看神器 jclasslib bytecode viewer》