Skip to content

Instantly share code, notes, and snippets.

@kriegaex
Last active January 19, 2024 06:41
Show Gist options
  • Save kriegaex/8228c8ba664c730157c2fef3c5fd78e7 to your computer and use it in GitHub Desktop.
Save kriegaex/8228c8ba664c730157c2fef3c5fd78e7 to your computer and use it in GitHub Desktop.
An example agent that intercepts bootstrap class method String::concat. Tested with Byte Buddy 1.14.11 on JDKs 8 to 21. Based on a question about https://gist.github.com/kriegaex/0f4dd4c9d05f3a68e3a8e1ed75359c3b.
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.Advice.*;
import net.bytebuddy.dynamic.loading.ClassInjector;
import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import static net.bytebuddy.implementation.bytecode.assign.Assigner.Typing.DYNAMIC;
import static net.bytebuddy.matcher.ElementMatchers.*;
public class BootstrapAdviceAgent {
public static void main(String[] args) throws IOException, UnmodifiableClassException {
premain(null, ByteBuddyAgent.install());
System.out.println("Hi ".concat("there!"));
System.out.println("Hello ".concat("world!"));
System.out.println("Say ".concat("something."));
System.out.println("heLLo ".concat("again!"));
}
public static void premain(String arg, Instrumentation instrumentation) throws IOException, UnmodifiableClassException {
ClassInjector.UsingUnsafe.Factory factory = ClassInjector.UsingUnsafe.Factory.resolve(instrumentation);
AgentBuilder agentBuilder = new AgentBuilder.Default();
agentBuilder = agentBuilder.with(new AgentBuilder.InjectionStrategy.UsingUnsafe.OfFactory(factory));
ResettableClassFileTransformer transformer = agentBuilder
.disableClassFormatChanges()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.ignore(none())
.ignore(nameStartsWith("net.bytebuddy."))
.type(is(String.class))
.transform((builder, typeDescription, classLoader, module, protectionDomain) -> builder
.visit(Advice.to(MyAdvice.class).on(named("concat")))
)
.installOn(instrumentation);
}
public static class MyAdvice {
@OnMethodEnter(skipOn = OnDefaultValue.class)
public static boolean before(
@This(typing = DYNAMIC, optional = true) String target,
@Argument(value = 0, readOnly = false) String arg
) {
if (target.equalsIgnoreCase("Hello "))
arg = arg.toUpperCase();
return arg.endsWith("!");
}
}
}
@Ch35Tnut
Copy link

Thank you very much. It works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment