You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Assuming I have a class with a protected field, and that class is extended by another in a different package:
package org.hibernate.bytebuddy.playground.differentpackage;
public class MySuperClass {
protected int myField;
public void setMyField(int myField) {
this.myField = myField;
}
}
package org.hibernate.bytebuddy.playground;
import org.hibernate.bytebuddy.playground.differentpackage.MySuperClass;
public class MyClass extends MySuperClass {
public int myMethod() {
return 0;
}
}
If I create an advice that reads myField, and apply it to the subclass MyClass:
public class MyAdvice {
@Retention(RetentionPolicy.RUNTIME)
@interface FieldValue {
}
@Advice.OnMethodExit
public static void exit(@FieldValue Object fieldValue,
@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object returned)
throws Throwable {
returned = fieldValue;
}
}
Then applying the advice will fail with the following error:
java.lang.IllegalStateException: Cannot access protected int org.hibernate.bytebuddy.playground.differentpackage.MySuperClass.myField from class org.hibernate.bytebuddy.playground.MyClass_withAdvice
at net.bytebuddy.asm.Advice$OffsetMapping$ForField$Resolved.resolve(Advice.java:2558)
at net.bytebuddy.asm.Advice$OffsetMapping$ForField.resolve(Advice.java:2305)
at net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodExit.doApply(Advice.java:8932)
at net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodExit.apply(Advice.java:8890)
at net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$AdviceMethodInliner.visitMethod(Advice.java:8312)
at net.bytebuddy.jar.asm.ClassReader.readMethod(ClassReader.java:1353)
at net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:744)
at net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:424)
at net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$AdviceMethodInliner.apply(Advice.java:8306)
at net.bytebuddy.asm.Advice$AdviceVisitor$WithExitAdvice.onUserEnd(Advice.java:10797)
at net.bytebuddy.asm.Advice$AdviceVisitor.visitMaxs(Advice.java:10576)
at net.bytebuddy.asm.Advice$Appender$EmulatingMethodVisitor.resolve(Advice.java:11148)
at net.bytebuddy.asm.Advice$Appender.apply(Advice.java:11100)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:709)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:694)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:601)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:5857)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:2192)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:232)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:204)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3659)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:3897)
at org.hibernate.bytebuddy.playground.MyTest.test(MyTest.java:31)
Expected behavior
I would expect this advice to work fine. The error message is wrong: class org.hibernate.bytebuddy.playground.MyClass_withAdvice definitely can access protected int org.hibernate.bytebuddy.playground.differentpackage.MySuperClass.myField, because MyClass_withAdvice extends MySuperClass, the field has protected access, and we know we're accessing a field of the same instance.
I think net.bytebuddy.asm.Advice$OffsetMapping$ForField$Resolved.resolve should probably call isVisibleTo rather than isAccessibleTo, because we know we're accessing a field of the same instance.
Unless net.bytebuddy.asm.Advice$OffsetMapping$ForField$Resolved.resolve can be used in cases where the field being accessed is located on another instance, in which case... I really don't know what is going on :)
Yes, you are completely right about this. I fixed this on master. I am planning a release in the next week which comes with some additional Graal support. It will include this fix.
Description of the problem
Assuming I have a class with a protected field, and that class is extended by another in a different package:
If I create an advice that reads
myField
, and apply it to the subclassMyClass
:Then applying the advice will fail with the following error:
Expected behavior
I would expect this advice to work fine. The error message is wrong: class
org.hibernate.bytebuddy.playground.MyClass_withAdvice
definitely can accessprotected int org.hibernate.bytebuddy.playground.differentpackage.MySuperClass.myField
, becauseMyClass_withAdvice
extendsMySuperClass
, the field has protected access, and we know we're accessing a field of the same instance.Reproducer
See https://github.com/yrodiere/bytebuddy-playground/tree/protected-field . Just run with
./mvnw clean test
.Possible cause
I think
net.bytebuddy.asm.Advice$OffsetMapping$ForField$Resolved.resolve
should probably callisVisibleTo
rather thanisAccessibleTo
, because we know we're accessing a field of the same instance.Unless
net.bytebuddy.asm.Advice$OffsetMapping$ForField$Resolved.resolve
can be used in cases where the field being accessed is located on another instance, in which case... I really don't know what is going on :)See also
Downstream reports:
May be related to #976.
The text was updated successfully, but these errors were encountered: