英文:
How to replace input arguments using ByteBuddy's @Advice.AllArguments?
问题
我正在使用ByteBuddy的@Advice
来转换我的类,一切都运行正常,直到我尝试替换输入参数。
我有一个名为FooService
的类,其中有一个join
方法,它只是将两个字符串用空格连接起来。
public class FooService {
public String join(String message, String message1) {
return message + " " + message1;
}
}
我还有另一个方法,它接受一个Object[] args
数组输入,并更改数组中的元素。
public static ArgsProcessor argsProcessor = args -> {
args[0] = args[0] + "-suffix";
args[1] = "replaced";
};
我尝试了不同的方法来使用argsProcessor
在@Advice.OnMethodEnter
方法中操作输入参数。对我来说,以下的advice实现几乎是等效的,应该都能工作,但令人费解的是只有Advice1
能正常工作。
public static class Advice1 {
@Advice.OnMethodEnter
public static void onEnter(@Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] args) {
Object[] newArgs = Arrays.copyOf(args, args.length);
ArgsProcessor argsProcessor = Demo.argsProcessor;
argsProcessor.process(newArgs);
args = newArgs;
}
}
public static class Advice2 {
@Advice.OnMethodEnter
public static void onEnter(@Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] args) {
Object[] newArgs = new Object[args.length];
ArgsProcessor argsProcessor = Demo.argsProcessor;
argsProcessor.process(args);
System.arraycopy(args, 0, newArgs, 0, args.length);
args = newArgs;
}
}
public static class Advice3 {
@Advice.OnMethodEnter
public static void onEnter(@Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] args) {
Object[] newArgs = Arrays.copyOf(args, args.length);
try {
ArgsProcessor argsProcessor = Demo.argsProcessor;
argsProcessor.process(newArgs);
args = newArgs;
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public static class Advice4 {
@Advice.OnMethodEnter
public static void onEnter(@Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] args) {
ArgsProcessor argsProcessor = Demo.argsProcessor;
argsProcessor.process(args);
}
}
public static class Advice5 {
@Advice.OnMethodEnter
public static void onEnter(@Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] args) {
ArgsProcessor argsProcessor = Demo.argsProcessor;
argsProcessor.process(args);
args = Arrays.copyOf(args, args.length);
}
}
输出结果:
Advice1 a-suffix replaced
Advice2 a b
Advice3 a b
Advice4 a b
Advice5 a b
代码片段链接:https://gist.github.com/raptium/ab7830e5d7f7cba43bbd2c2a5c7b38e0
英文:
I am using ByteBuddy's @Advice
to transform my classes and it works fine until I try to replace input arguments.
I have a FooService
with a join
method which just joins two strings with a space.
public class FooService {
public String join(String message, String message1) {
return message + " " + message1;
}
}
And I have another method which takes a Object[] args
array input and changes elements in the array.
public static ArgsProcessor argsProcessor = args -> {
args[0] = args[0] + "-suffix";
args[1] = "replaced";
};
I've tried different ways to use the argsProcessor
to manipulate the input arguments in @Advice.OnMethodEnter
method. For me, the following advice implementations are almost equivalent and should all work, somehow only Advice1
works.
public static class Advice1 {
@Advice.OnMethodEnter
public static void onEnter(@Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] args) {
Object[] newArgs = Arrays.copyOf(args, args.length);
ArgsProcessor argsProcessor = Demo.argsProcessor;
argsProcessor.process(newArgs);
args = newArgs;
}
}
public static class Advice2 {
@Advice.OnMethodEnter
public static void onEnter(@Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] args) {
Object[] newArgs = new Object[args.length];
ArgsProcessor argsProcessor = Demo.argsProcessor;
argsProcessor.process(args);
System.arraycopy(args, 0, newArgs, 0, args.length);
args = newArgs;
}
}
public static class Advice3 {
@Advice.OnMethodEnter
public static void onEnter(@Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] args) {
Object[] newArgs = Arrays.copyOf(args, args.length);
try {
ArgsProcessor argsProcessor = Demo.argsProcessor;
argsProcessor.process(newArgs);
args = newArgs;
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public static class Advice4 {
@Advice.OnMethodEnter
public static void onEnter(@Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] args) {
ArgsProcessor argsProcessor = Demo.argsProcessor;
argsProcessor.process(args);
}
}
public static class Advice5 {
@Advice.OnMethodEnter
public static void onEnter(@Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] args) {
ArgsProcessor argsProcessor = Demo.argsProcessor;
argsProcessor.process(args);
args = Arrays.copyOf(args, args.length);
}
}
Output
Advice1 a-suffix replaced
Advice2 a b
Advice3 a b
Advice4 a b
Advice5 a b
The code snippet https://gist.github.com/raptium/ab7830e5d7f7cba43bbd2c2a5c7b38e0
答案1
得分: 1
运行您的代码,我得到以下结果:
Advice1 a-suffix替换
Advice2 a b
Advice3 a-suffix替换
Advice4 a b
Advice5 a b
这正是我期望的结果。Byte Buddy将advice方法用作模板。此代码实际上并未被执行。当您在方法中读取args
时,Byte Buddy 每次都会创建一个新数组。
因此,计算args == args
会返回false
,因为Byte Buddy每次都会创建一个包含所有参数的新数组!如果您更改了args数组,您必须将其写回以便Byte Buddy能够发现相应的字节码,并将其映射回赋值。
英文:
Running your code, I get
Advice1 a-suffix replaced
Advice2 a b
Advice3 a-suffix replaced
Advice4 a b
Advice5 a b
what is what I expect. Byte Buddy uses advice methods as templates. This code is not really exeucted. When you read args
in your method, Byte Buddy creates a new array every time.
Therefore, computing args == args
would return false
since Byte Buddy creates a new array containing all arguments every time! If you change the args array, you have to write it back for Byte Buddy to discover the corresponding byte code and to map it back to an assignment.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论