Search code examples
javaosgibyte-buddy

ByteBuddy rebasing, synthetic types and OSGi


I have the following interceptor developed for byte-buddy:

public class SecurityInterceptor() {

    @RuntimeType
    public static Object intercept(
        @SuperCall Callable<Object> supercall, 
        @This Object target, 
        @Origin Method method, 
        @AllArguments Object[] args) {  

        // Check args and annotations ...       

        Object obj = supercall.call();

        // Post-process obj content ...
    }
}

The interceptor is registered as follows:

Unloaded<Object> unloaded = new ByteBuddy()
    .rebase(type, classFileLocator)
    .method(ElementMatchers.isAnnotatedWith(Secured.class))
    .intercept(MethodDelegation.to(SecurityInterceptor.class))
    .make();
wovenClass.setBytes(unloaded.getBytes());

and this happens inside a WeavingHook in OSGi. The problem is that rebasing with @SuperCall alters the original code as such

public User getUser(final String s) throws Exception {
    return SecurityInterceptor.intercept((Callable)new UsersServiceImpl$auxiliary$xhbBRSr4(this, s), 
        (Object)this, UsersServiceImpl.cachedValue$nlgHrwy3$sn5qca3, new Object[] { s });
}

where UsersServiceImpl$auxiliary$xhbBRSr4 is a synthetic class that is generated by byte-buddy:

class UsersServiceImpl$auxiliary$xhbBRSr4 implements Runnable, Callable
{
    private UsersServiceImpl argument0;
    private String argument1;

    @Override
    public Object call() throws Exception {
        return this.argument0.getUser$original$6ve6X5gN$accessor$nlgHrwy3(this.argument1);
    }

    @Override
    public void run() {
        this.argument0.getUser$original$6ve6X5gN$accessor$nlgHrwy3(this.argument1);
    }

    UsersServiceImpl$auxiliary$xhbBRSr4(final UsersServiceImpl argument0, final String argument2) {
        this.argument0 = argument0;
        this.argument1 = argument2;
    }
}

where UsersServiceImpl is the class being weaved.

So what I need is to add all these synthetic classes in the class space of the UsersServiceImpl's bundle (or in general make synthetic classes "accessible" from that bundle). Is this possible?


Solution

  • In the end I used a different approach:

    Unloaded<Object> unloaded = new ByteBuddy()
        .redefine(type, classFileLocator)
        .visit(Advice.to(SecurityAdvice.class)
                .on(ElementMatchers.isAnnotatedWith(Secured.class)))
        .make();
    

    with

    public class SecurityAdvice {
        @Advice.OnMethodEnter
        private static void enter(@Advice.AllArguments Object[] args) {
            //...
        }
    
        @Advice.OnMethodExit
        private static void exit(@Advice.Return(typing = Typing.DYNAMIC) Object value) {
           //...
        }
    }
    

    this only alters the original class's bytecode without introducing additional synthetic types.