Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Piping methods with void return type #9

Closed
tomola opened this issue Nov 25, 2014 · 5 comments
Closed

Piping methods with void return type #9

tomola opened this issue Nov 25, 2014 · 5 comments
Assignees
Labels
Milestone

Comments

@tomola
Copy link

tomola commented Nov 25, 2014

I'm currently porting one of our libraries from CGLib to ByteBuddy and I've encounter a problem with @pipe. I've got a simple proxy that delegates all calls to the wrapped target object. Everything is OK until there is a method returning void on the target object.

My setup is like:

public class X {
    public static class WrappedObject {
        Object method1() {...}
        void method2() {...}
    }

    public static interface Forwarder<T, S> {
        T to(S target);
    }

    public static class Handler {
        protected final WrappedObject wrappedObject;

        public Handler(WrappedObject wrappedObject) {
            this.wrappedObject = wrappedObject;
        }

        @RuntimeType
        public Object delegate(@Pipe Forwarder<Object, WrappedObject> pipe) {
            return pipe.to(wrappedObject);
        }
    }

    public static void main(String... args) throws Exception {
        WrappedObject proxiedObject = new ByteBuddy()
          .subclass(WrappedObject.class)
          .method(any())
          .intercept(MethodDelegation.to(new Handler(new WrappedObject())).appendParameterBinder(Pipe.Binder.install(Forwarder.class)))
          .make()
          .load(X.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
          .getLoaded()
          .newInstance();
    }
}

The proxy cannot be created:

Exception in thread "main" java.lang.IllegalStateException: An illegal stack manipulation must not be applied
    at net.bytebuddy.instrumentation.method.bytecode.stack.StackManipulation$Illegal.apply(StackManipulation.java:46)
    at net.bytebuddy.instrumentation.method.bytecode.stack.StackManipulation$Compound.apply(StackManipulation.java:194)
    at net.bytebuddy.instrumentation.method.bytecode.bind.annotation.Pipe$Binder$Redirection$MethodCall$Appender.apply(Pipe.java:589)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Entry$Simple.apply(TypeWriter.java:1055)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Engine$ForCreation.create(TypeWriter.java:688)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1143)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:219)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$AbstractDelegatingBuilder.make(DynamicType.java:1611)
    at net.bytebuddy.instrumentation.method.bytecode.bind.annotation.Pipe$Binder$Redirection.make(Pipe.java:332)
    at net.bytebuddy.instrumentation.Instrumentation$Context$Default.register(Instrumentation.java:808)
    at net.bytebuddy.instrumentation.method.bytecode.bind.annotation.Pipe$Binder$Redirection.apply(Pipe.java:342)
    at net.bytebuddy.instrumentation.method.bytecode.bind.MethodDelegationBinder$ParameterBinding$Anonymous.apply(MethodDelegationBinder.java:192)
    at net.bytebuddy.instrumentation.method.bytecode.bind.MethodDelegationBinder$MethodBinding$Builder$Build.apply(MethodDelegationBinder.java:507)
    at net.bytebuddy.instrumentation.method.bytecode.stack.StackManipulation$Compound.apply(StackManipulation.java:194)
    at net.bytebuddy.instrumentation.MethodDelegation$Appender.apply(MethodDelegation.java:998)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Entry$Simple.apply(TypeWriter.java:1055)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Engine$ForCreation.create(TypeWriter.java:688)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1143)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:219)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$AbstractDelegatingBuilder.make(DynamicType.java:1611)
    at X.main(X.java:40)

When I change WrappedObject class to:

    public static class WrappedObject {
        Object method1() {...}
        Object method2() {...}
    }

it runs fine.

So, is @pipe capable of delegation to void returning methods? Or am I doing something wrong?

@raphw raphw added the bug label Nov 25, 2014
@raphw raphw added this to the 0.5 milestone Nov 25, 2014
@raphw raphw self-assigned this Nov 25, 2014
@raphw
Copy link
Owner

raphw commented Nov 25, 2014

This is indeed a bug, rather a faulty default setup. You can resolve this by setting a different Assigner which knows how to assign a void type to an Object type.

When defining the MethodDelegation, set

new VoidAwareAssigner(new PrimitiveTypeAwareAssigner(ReferenceTypeAwareAssigner.INSTANCE), true)

using the withAssigner method.

This is of course inconvenient and the upcoming version will provide a better solution and you will not longer be required to do so. Thanks for reporting this and for using Byte Buddy.

@raphw raphw modified the milestones: 0.4.1, 0.5 Nov 26, 2014
@raphw
Copy link
Owner

raphw commented Nov 26, 2014

As a matter of fact, due to another bug, I planed a bug-fix release later this day. Simply upgrade to version 0.4.1 once this version is available.

@raphw
Copy link
Owner

raphw commented Nov 26, 2014

The bug-fix release 0.4.1 is already available in JCenter and is currently synchronized to Maven Central. It should be available from there in a couple of hours.

@raphw raphw closed this as completed Nov 26, 2014
@tomola
Copy link
Author

tomola commented Nov 26, 2014

Thanks Rafael, I can confirm now it works as I expected.

@raphw
Copy link
Owner

raphw commented Nov 26, 2014

You are welcome. And thanks for reporting this and helping to improve Byte Buddy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants