注入Java方法_before_调用另一个方法

Dav*_*vid 11 java bytecode-manipulation java-bytecode-asm

我正在使用ASM并希望重写类似的东西:

someMethod().targetMethod(args...)
Run Code Online (Sandbox Code Playgroud)

至:

someMethod().injectedMethod(arg).targetMethod(args...)
Run Code Online (Sandbox Code Playgroud)

问题是我不知道之前的方法是什么,我只知道目标方法(因此找不到someMethod()并注入之后不是一个选项).

我还有许多版本的目标方法,我想要使用不同的参数集.

使用ASM我可以很容易地找到目标方法调用,但不幸的是,那时的操作数堆栈是:

[ argN, ..., arg1, instance, ... ]
Run Code Online (Sandbox Code Playgroud)

虽然我可以计算出实例的距离,但是我没有可以注入的字节码会读取它.我知道你可以使用带有dup命令的技巧最多4个参数,但我需要一个通用的解决方案.

我可以添加一堆局部变量并将所有内容复制到堆栈中,复制指向的实例并重新打开所有内容,但这是我真正不想要的运行时效率低下.

我认为可行的是,如果我可以跟踪哪个指令负责将实例指针放在堆栈上,然后我可以在那里注入我的方法调用而不是在目标方法调用.但是,我没有找到任何帮助我做这件事的运气.

我知道像AspectJ这样的东西允许这样做,但是必须在很多类中执行此操作,因为它们加载并且AspectJ太慢了.

任何人都可以指出我在ASM之上构建的分析工具可能让我这样做,或者任何人都可以想到一个更好的方法来在另一个之前注入一个方法调用?

Eug*_*hov 1

一般情况下,您可以将堆栈中的值卸载到临时局部变量中。ASM commons 包中的LocalVariableSorter适配器使其变得非常简单。但实际上,具有超过 4 个参数的方法是很少见的。无论如何,它仍然比在运行时进行全面的数据流分析更简单、更可靠。

ASM 的org.objectweb.asm.tree.analysis提供了数据流分析的工具,例如,您可以使用SourceInterpreter来跟踪哪些指令在每个变量和堆栈槽上生成了值。有关更多详细信息,请参阅ASM 用户指南。