-
-
Notifications
You must be signed in to change notification settings - Fork 809
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
Enhancing a class using Byte Buddy resulted in the generation of unexpected bytecode. #1758
Comments
There is indeed a little bug when it comes to default methods. It should now work with the master version of Byte Buddy. You can fortunately work-around this limitation with a little trick, simply define a second method in the interceptor:
Simply delegate to the original interceptor from it. |
Thank you for your explanation. And I hava another question。It also has default methods, but it not generate unexpected byte code instead of throw a exception. and the interface like this: public interface JedisCommands {
default Long expire(String key, int seconds) {
return expire(key, (long) seconds);
}
Long expire(String key, long seconds);
String setex(String key, long seconds, String value);
} the class implements the JedisCommands interface like this: public class Jedis implements JedisCommands {
@Override
public Long expire(String key, long seconds) {
return 100L;
}
@Override
public String setex(String key, long seconds, String value) {
return "test";
}
} The rest of the code is the same as the one above. and when I compile the code. it throw the exception like this: Exception in thread "main" java.lang.IllegalArgumentException: None of [protected void java.lang.Object.finalize() throws java.lang.Throwable, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException, public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll(), public java.lang.Object org.example.InstMethodsInterWithOverrideArgs.intercept(java.lang.Object,java.lang.Object[],java.lang.reflect.Method,org.example.OverrideCallable) throws java.lang.Throwable] allows for delegation from public java.lang.Long org.example.JedisCommands.expire(java.lang.String,int)
at net.bytebuddy.implementation.bind.MethodDelegationBinder$Processor.bind(MethodDelegationBinder.java:1099)
at net.bytebuddy.implementation.MethodDelegation$Appender.apply(MethodDelegation.java:1349)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:732)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:717)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:624)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor.onVisitEnd(TypeWriter.java:5340)
at net.bytebuddy.utility.visitor.MetadataAwareClassVisitor.visitEnd(MetadataAwareClassVisitor.java:325)
at net.bytebuddy.jar.asm.ClassVisitor.visitEnd(ClassVisitor.java:395)
at net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:749)
at net.bytebuddy.utility.AsmClassReader$Default.accept(AsmClassReader.java:132)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining.create(TypeWriter.java:4034)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:2246)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$UsingTypeWriter.make(DynamicType.java:4085)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3769)
at org.example.App.test2(App.java:69)
at org.example.App.main(App.java:24) My question is, why is the default setex method generating unexpected bytecode, whereas the default expire method is throwing an exception? |
Questtion description:
The problem is like this. When a class implements an interface with default methods, enhancing it with Byte Buddy may result in the generation of bytecode that does not meet expectations.
Version info:
the byte-buddy version is : 1.15.11
JDK is: 1.8
Test case:
To reproduce the issue, a simple test case in below.
A interface code:
this interface JedisCommands has three method and one method
setex(String, int, String)
has a default implements .the class implements the JedisCommands interface
A method delegation defines:
the OverrideCallable define:
the byte-buddy config:
I save the byte code in file and named ProxyJedis:
Question:
I can't understand why was the method
setex(String,int,String)
is delegated totoString
method instead ofintercept
method.The text was updated successfully, but these errors were encountered: