I am trying to explore and understand the bytebuddy library to create advice for one of the method. But I am encountering an exception upfront as below which seems a bit weird as given below:
Exception in thread "main" java.lang.IllegalStateException: Cannot locate field named name for class org.purbarun.proxy.MyService$ByteBuddy$8XL9Iy3U
at net.bytebuddy.asm.Advice$OffsetMapping$ForField$Unresolved.resolve(Advice.java:2534)
at net.bytebuddy.asm.Advice$OffsetMapping$ForField.resolve(Advice.java:2459)
at net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodEnter.doApply(Advice.java:9979)
at net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodEnter$WithDiscardedEnterType.doApply(Advice.java:10081)
at net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodEnter.apply(Advice.java:9937)
at net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$AdviceMethodInliner.visitMethod(Advice.java:9620)
at net.bytebuddy.jar.asm.ClassReader.readMethod(ClassReader.java:1354)
at net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:745)
at net.bytebuddy.utility.AsmClassReader$ForAsm.accept(AsmClassReader.java:225)
at net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$AdviceMethodInliner.apply(Advice.java:9613)
at net.bytebuddy.asm.Advice$AdviceVisitor.onAfterExceptionTable(Advice.java:11919)
at net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor.considerEndOfExceptionTable(ExceptionTableSensitiveMethodVisitor.java:49)
at net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor.visitVarInsn(ExceptionTableSensitiveMethodVisitor.java:113)
at net.bytebuddy.implementation.bytecode.member.MethodVariableAccess$OffsetLoading.apply(MethodVariableAccess.java:354)
at net.bytebuddy.implementation.bytecode.StackManipulation$Compound.apply(StackManipulation.java:243)
at net.bytebuddy.implementation.SuperMethodCall$Appender.apply(SuperMethodCall.java:139)
at net.bytebuddy.asm.Advice$Appender$EmulatingMethodVisitor.resolve(Advice.java:12525)
at net.bytebuddy.asm.Advice$Appender.apply(Advice.java:12478)
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$ForCreation.create(TypeWriter.java:6072)
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 net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:4021)
at org.purbarun.proxy.MainRunner.main(MainRunner.java:14)
My code as given below should be very simple and straightforward as I am quite new to this:
public class MyService {
public void myMethod(String args) {
System.out.println(args);
}
}
public class MyServiceInterceptor {
@OnMethodEnter
static void enter(@This Object thisObject,
@Origin String origin,
@Origin("#t #m") String detaildOrigin,
@AllArguments Object[] ary,
@FieldValue(value = "name", readOnly = false) String nameField){
System.out.println("test");
}
}
public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException, InstantiationException, IllegalArgumentException {
Class<? extends MyService> type=new ByteBuddy()
.subclass(MyService.class)
.method(ElementMatchers.isMethod()).intercept(Advice.to(MyServiceInterceptor.class))
.make()
.load(MyService.class.getClassLoader())
.getLoaded();
String returnVal = (String)type.getDeclaredMethod("myMethod", String.class).invoke(type.getDeclaredConstructor().newInstance(), "Method");
System.out.println("return value: " + returnVal);
}
Not sure if I am doing kind of silly mistakes which I am not able to get.
Can anyone from the community help me out to figure out the error.
If you don't have a name
field in MyService
simply remove the @FieldValue
parameter from your advice:
@OnMethodEnter
static void enter(
@This Object thisObject,
@Origin String origin,
@Origin("#t #m") String detaildOrigin,
@AllArguments Object[] ary
// Remove: @FieldValue(value = "name", readOnly = false) String nameField
) {
System.out.println("test");
}
If you do plan to access a field from the original class via @FieldValue
, ensure that the field exists in the class:
public class MyService {
public String name; // Must exist to be accessible with @FieldValue
public void myMethod(String args) {
System.out.println(args);
}
}