byte-buddy

Completely redirecting calls to a static method with byte-buddy


I have a project that reads the contents of a jar file, modifies selected static methods in specific classes in that jar file so that they point to different static methods, then rewrites the jar file. This part is working.

However, I have seen that instead of only calling the different static methods, these intercepted calls first call the original method. I need to prevent this from happening.

My code currently only uses a method with the @Advice.OnMethodExit annotation, because I needed to ensure I am returning the correct value (from the new method). Unfortunately, the some of the original methods have side effects that can cause problems, or even cause runtime failures in the environment they would be executed in (part of the reason for modifying them in the first place).

My current 'Advice' class (for a simple test) looks like this:

class StringRedirect extends RedirectAdvice {
    @Advice.OnMethodExit
    public static String intercept(@Advice.Origin("#t.#m") String methodSignature,
                                   @Advice.AllArguments Object[] args,
                                   @Advice.Return(readOnly = false) String returnValue) throws Exception {

        MethodRedirectDescriptor descriptor = REDIRECT_MAP.get(methodSignature);
        if (descriptor != null) {
            ClassLoader jarClassLoader = Thread.currentThread().getContextClassLoader();

            // Get the method to use instead from the descriptor
            Method targetMethod = descriptor.getTargetMethod(jarClassLoader);

            returnValue = (String) targetMethod.invoke(null, args);
        }

        return returnValue;
    }
}

The descriptor is a data structure that is used to define specific pieces of the methods to be intercepted and the methods that should be called instead. And, of course, REDIRECT_MAP is a map of these descriptors.

As I said, this is working - in so far as the new target methods are being called. However, I need to prevent the original methods from being invoked in the first place. I looked at @Advice.OnMethodEnter but couldn't find a way to tell it to not actually invoke the original method.

The relevant code from the driver application (that reads the jar file and uses byte-buddy to modify it) looks like this:

// get class name to modify and put in className variable
// get a descriptor for that class
// 
...
byte[] modifiedClass = new ByteBuddy()
    .redefine(typePool.describe(className).resolve(), locator)
    .visit(Advice.to(descriptor.getAdviceClass())
                 .on(ElementMatchers.named(descriptor.getOriginalMethodName())))
    .make()
    .getBytes();

Is there a way to do this?


Solution

  • You have multiple options here: