Byte Buddy seems to only appreciate public classes as interceptor implementations even if I provide the actual instance; frequently I find myself wanting to do something like this:
import static MethodDelegation.to;
new ByteBuddy().subclass(Object.class).method(any()).intercept(to(new Object() {
@RuntimeType
public Object intercept(@Origin Method m, @AllArguments Object[] a) {
return null;
}
});
Which however results in an exception as follows:
Exception in thread "main" java.lang.IllegalStateException: class net.bytebuddy.renamed.java.lang.Object$ByteBuddy$pUmdGhyP cannot access class us.levk.guice.vs.Scopes$1Builder$1
Is there any reason behind visibility enforcement?
EDIT: I'm still having trouble with it though; I'm getting a different exception, this is my code:
package us.levk.guice.vs;
import static net.bytebuddy.implementation.MethodDelegation.to;
import static net.bytebuddy.matcher.ElementMatchers.any;
import java.lang.reflect.Method;
import java.util.function.Function;
import java.util.function.Supplier;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
public class Bar {
Function<Supplier<?>, Class<?>> wrapper () {
return s -> {
return new ByteBuddy ().subclass (Object.class)
.name (Bar.class.getPackage ().getName () + ".Foo")
.method (any ())
.intercept (to (new Object () {
@RuntimeType
public Object intercept (@Origin Method method,
@AllArguments Object[] args) {
System.out.println (method);
return null;
}
}))
.make ()
.load (getClass ().getClassLoader (),
ClassLoadingStrategy.Default.WRAPPER)
.getLoaded ();
};
}
public static void main (String[] args) throws InstantiationException, IllegalAccessException {
new Bar ().wrapper ().apply ( () -> new Integer (1)).newInstance ().toString ();
}
}
And the exception is now:
Exception in thread "main" java.lang.IllegalAccessError: tried to access class us.levk.guice.vs.Bar$1 from class us.levk.guice.vs.Foo
EDIT2:
It works fine if I change the classloading strategy to INJECTION
In this case, Byte Buddy informs you about a visibility constraint that would cause an IllegalAccessException
at runtime.
Eventhough you declare your method public
, the anonymous class is automatically defined to be package private by javac. Therefore, the method is not visible to the generated class since net.bytebuddy.renamed.java.lang.Object
is not equal to us.levk.guice.vs.Scopes
.
If you did:
new ByteBuddy().subclass(Object.class).name("us.levk.guice.vs.Foo")
.method(any()).intercept(to(new Object() {
@RuntimeType
public Object intercept(@Origin Method m, @AllArguments Object[] a) {
return null;
}
}));
everything would work. Alternatively, you can define - for example - a public interface such as:
public interface Foo {
@RuntimeType
Object intercept(@Origin Method m, @AllArguments Object[] a);
}
new ByteBuddy().subclass(Object.class).name("us.levk.guice.vs.Foo")
.method(any()).intercept(to(new Foo() {
@RuntimeType
public Object intercept(@Origin Method m, @AllArguments Object[] a) {
return null;
}
}, Foo.class));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With