【Arthas】Arthas线上trace匿名函数/Lambda表达式/函数式接口

2023-12-26 13:29:54

前言

Arthas是一个非常牛B的东西,我非常喜欢用,特别是在定义线上问题的时候,牛逼大发!
非常建议所有Java玩家都去学习一下

阅读对象

  1. 了解并使用过Arthas
  2. 了解并使用过trace命令

先说结论

先说结论,lambda表达式的追踪,大概格式如下:
假设你的lambda表达式写在函数Demo类的test方法里面,正常trace是:trace Demo test。但如果你的test方法,里面有lambda表达式,你想要trace里面的内容,你大概需要这么改:trace Demo lambda$test$0

我也不是很理解那个0是啥意思,我猜测是test方法内第几个lambda表达式的意思,然后是从0开始

如果你看了结论之后,没办法解决你的问题,那就往下看,仔细看完吧。

RT

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,再深层的invokevirtual,它并不能知道。
总结一下就是: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匿名函数

这里就不多解释了,把你的trace Demo test,改成trace Demo lambda$test$0就好了
当然,我们已经知道了字节码命名风格之后,可以不用安装上面说的字节码插件了,就按照这种命名方式trace即可。

感谢

感谢百度大佬【作者:程序员子悠】的文章《IDEA 字节码学习查看神器 jclasslib bytecode viewer

文章来源:https://blog.csdn.net/qq_32681589/article/details/135218274
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。