raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.23k stars 804 forks source link

how i use advice to match java.util.regex.Pattern #1564

Closed cor0ps closed 6 days ago

cor0ps commented 10 months ago
this  is  I  want  matches  java.util.regex.Pattern
  new AgentBuilder.Default().type(ElementMatchers.nameMatches("java.util.regex.Pattern"))
                .transform(patternTransformer)

I  want  use   Advice 
   AgentBuilder.Transformer patternTransformer = (builder, typeDescription, classLoader, javaModule, protectionDomain) -> builder

                .method(ElementMatchers.nameMatches("matcher"))
                //委托
                .intercept(Advice.to(PatternAdvice.class));

PatternAdvice.class

public class PatternAdvice {

    @Advice.OnMethodEnter
    public static void MethodEnter(@Advice.Origin Method method, @Advice.AllArguments Object[] args) {

    }

}

first I add this agent.jar to instrumentation.appendToBootstrapClassLoaderSearch(new JarFile(xxx));

this is error

I use instrumentation.appendToSystemClassLoaderSearch it works,but not matches java.util.regex.Pattern ,how I solve it

raphw commented 10 months ago

You want to use Advice as decorator via builder.visit(...). Then the code is inlined. Generally speaking, I recommend against intercepting such a central class, though, as Byte Buddy relies on it itself what can cause circularities.

cor0ps commented 10 months ago

how can I solve this problem ,why i always not mathes java.util.regex but I can mathes java.lang.Runtime ....

cor0ps commented 10 months ago

I find bytebuddy stacks, java.util.regex.Pattern always upper bytebuddy

at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$LegacyVmDispatcher.run(AgentBuilder.java:12507)
    at java.security.AccessController.doPrivileged(Native Method)
    at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doPrivileged(AgentBuilder.java)
    at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:12069)
    at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
    at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
    at java.util.regex.Pattern.intersection(Pattern.java:5273)
    at java.util.regex.Pattern.clazz(Pattern.java:2551)
    at java.util.regex.Pattern.sequence(Pattern.java:2077)
    at java.util.regex.Pattern.expr(Pattern.java:2010)
    at java.util.regex.Pattern.compile(Pattern.java:1702)
    at java.util.regex.Pattern.<init>(Pattern.java:1352)
    at java.util.regex.Pattern.compile(Pattern.java:1028)
raphw commented 10 months ago

You'd have to avoid them manually, for example by checking the call site's stack and to suppress your modifications. Byte Buddy does not interfere with this as it is only applying your instrumentation.

cor0ps commented 10 months ago

I'm really confused about this. I can't figure out why I can't intercept it java.util.regex.Pattern this class in boot loader 。

raphw commented 10 months ago

You need to register an ignore matcher that allows for intercepting the boot loader. Check the ignore step in the builder API.

dogourd commented 10 months ago

Perhaps it's because the internal implementation of ElementMatchers.nameMatches(java.lang.String) further relies on java.util.regex.Pattern.
If you already have the specific class name, have you tried using ElementMatchers.named(java.lang.String) for matching instead?

januslinhc commented 8 months ago

You need to register an ignore matcher that allows for intercepting the boot loader. Check the ignore step in the builder API.

Hi @raphw , I added the ignore matcher, however, I still can not intercept any classes from JDK like java.util.ArrayList. Would be great if you can give me some hints.


        install(arg, inst);
    }

    public static void agentmain(String arg, Instrumentation inst) throws IOException {
        install(arg, inst);
    }

    private static void install(String arg, Instrumentation inst) throws IOException {
        new AgentBuilder.Default()
                .ignore(none())
                .type(any().and(not(nameStartsWith("net.bytebuddy.")))
                        .and(not(nameStartsWith("de.scrum_master.bytebuddy.")))
                        .and(not(nameStartsWith("java.lang.invoke.BoundMethodHandle$Species_L")))
                        .and(not(nameStartsWith("com.sun.proxy.$Proxy")))
                        .and(not(named("java.lang.UnsupportedOperationException")))
                        .and(not(nameStartsWith("org.junit.")))
                        .and(not(nameStartsWith("org.objectweb.asm.")))
                        .and(not(nameStartsWith("com.intellij."))))
                .transform(new AgentBuilder.Transformer.ForAdvice().advice(ElementMatchers.isConstructor(), ConstructorInterceptor.class.getName()))
                .installOn(inst);
    }```
raphw commented 8 months ago

You need to use with(RetransformationStrategy.RETRANSFORM) as those classes will already be loaded when your agent is installed. Use disableClassFormatChanges(), too, as retransformation is not capable of all forms of transformation.