简体   繁体   中英

How to call original method after MethodDelegation using java agent and byte buddy?

Recently I start to play around byte buddy and try to hook some Java methods. I try to hook readBoolean from java.io.ObjectInputStream. It works fine if I always return true or false. However I can not make it work if I only want the first call to return false, and the rest return whatever from the original hooked method. Here is my code:

    new AgentBuilder.Default()
            .with(RedefinitionStrategy.RETRANSFORMATION)
            .with(InitializationStrategy.NoOp.INSTANCE)
            .with(TypeStrategy.Default.REDEFINE)
            .ignore(new AgentBuilder.RawMatcher.ForElementMatchers(nameStartsWith("net.bytebuddy.").or(isSynthetic()), any(), any()))
            .with(new Listener.Filtering(
                    new StringMatcher("java.io.ObjectInputStream", StringMatcher.Mode.EQUALS_FULLY),
                    Listener.StreamWriting.toSystemOut()))
            .type(named("java.io.ObjectInputStream"))  //class
            .transform((builder, type, classLoader, module) ->
                            builder.method(ElementMatchers.nameContains("readBoolean"))
                                   .intercept(MethodDelegation.to(INTERCEPTOR_CLASS))
            )
            .installOn(inst);

In the INTERCEPTOR_CLASS, only the following works:

public static boolean readBoolean(@Origin Method m) throws Exception{
    LOGGER.log(Level.INFO, "In "+ m.getName());
    return true;
}

It's wrong and has some running exception if I try to use @Super Callable.

Also if I try to use Advice.to(INTERCEPTOR_CLASS) and @Advice.OnMethodExit, I can not use @Advice.Return to set the return to true or false. It seems not work to set the return value for primitive.

There is no change if I change TypeStrategy.Default.REDEFINE to TypeStrategy.Default.REBASE

I read the document again and again, seems still no clue. Thank you for pointing me a right direction.

If you only want the first call to be intercepted, you would need to add some form of state management. In the simplest case, you can set a system property after the call and check if it is already set before doing it.

Advice is probably the best option for you. It should work, if not please create a reproducer project. If you wanted to use delegation, you need to register a bootstrap-capable injection strategy .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM