Created
May 29, 2020 02:11
-
-
Save raptium/ab7830e5d7f7cba43bbd2c2a5c7b38e0 to your computer and use it in GitHub Desktop.
How to replace input arguments using ByteBuddy's @Advice.AllArguments?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static net.bytebuddy.matcher.ElementMatchers.is; | |
import net.bytebuddy.ByteBuddy; | |
import net.bytebuddy.agent.ByteBuddyAgent; | |
import net.bytebuddy.agent.builder.AgentBuilder; | |
import net.bytebuddy.agent.builder.ResettableClassFileTransformer; | |
import net.bytebuddy.asm.Advice; | |
import net.bytebuddy.asm.AsmVisitorWrapper; | |
import net.bytebuddy.implementation.bytecode.assign.Assigner; | |
import net.bytebuddy.matcher.ElementMatchers; | |
import java.lang.instrument.Instrumentation; | |
import java.util.Arrays; | |
public class Demo { | |
public static ArgsProcessor argsProcessor = args -> { | |
args[0] = args[0] + "-suffix"; | |
args[1] = "replaced"; | |
}; | |
public static void main(String[] args) { | |
Instrumentation instrumentation = ByteBuddyAgent.install(); | |
Demo demo = new Demo(); | |
try { | |
demo.run(instrumentation, Advice1.class); | |
demo.run(instrumentation, Advice2.class); | |
demo.run(instrumentation, Advice3.class); | |
demo.run(instrumentation, Advice4.class); | |
demo.run(instrumentation, Advice5.class); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
public void run(Instrumentation instrumentation, Class<?> adviceClass) throws Exception { | |
FooService fooService = new FooService(); | |
ByteBuddy byteBuddy = new ByteBuddy(); | |
ResettableClassFileTransformer transformer = new AgentBuilder.Default() | |
.with(byteBuddy) | |
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) | |
.disableClassFormatChanges() | |
.type(is(FooService.class)) | |
.transform((builder, typeDescription, classloader, module) -> { | |
AsmVisitorWrapper.ForDeclaredMethods advice = Advice.to(adviceClass) | |
.on(ElementMatchers.named("join")); | |
return builder.visit(advice); | |
}).installOnByteBuddyAgent(); | |
String c = fooService.join("a", "b"); | |
System.out.printf("%s %s\n", adviceClass.getSimpleName(), c); | |
transformer.reset(instrumentation, AgentBuilder.RedefinitionStrategy.RETRANSFORMATION); | |
} | |
public static interface ArgsProcessor { | |
void process(Object[] args); | |
} | |
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); | |
} | |
} | |
public static class FooService { | |
public String join(String message, String message1) { | |
return message + " " + message1; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment