ByteBuddy报错:无法定位类中name字段,请求社区协助排查
问题排查:ByteBuddy Advice中无法找到name字段的异常
我正在探索ByteBuddy库,尝试为方法创建Advice,但运行时抛出java.lang.IllegalStateException异常,提示无法找到org.purbarun.proxy.MyService$ByteBuddy$8XL9Iy3U类中的name字段。以下是异常信息和测试代码,请求帮忙排查错误。
异常信息
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)
测试代码
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); }
问题原因和解决方案
核心问题
MyService类中不存在name字段,但拦截器方法enter中使用@FieldValue("name")尝试获取该字段,ByteBuddy在生成代理类时无法找到对应字段,因此抛出异常。
解决方案
方案1:添加需要的字段(如果确实需要操作name字段)
在MyService类中添加name字段:
public class MyService { private String name; // 添加name字段 public void myMethod(String args) { System.out.println(args); } }
方案2:移除无用的字段参数(如果不需要操作name字段)
删除拦截器中@FieldValue相关的参数:
public class MyServiceInterceptor { @OnMethodEnter static void enter(@This Object thisObject, @Origin String origin, @Origin("#t #m") String detaildOrigin, @AllArguments Object[] ary){ System.out.println("test"); } }
额外修正点
myMethod是void返回类型,但main方法中强制将返回值转为String,会触发ClassCastException,需要修正main方法:
public static void main(String[] args) throws Exception { Class<? extends MyService> type = new ByteBuddy() .subclass(MyService.class) .method(ElementMatchers.isMethod()).intercept(Advice.to(MyServiceInterceptor.class)) .make() .load(MyService.class.getClassLoader()) .getLoaded(); // void方法无需接收返回值 type.getDeclaredMethod("myMethod", String.class) .invoke(type.getDeclaredConstructor().newInstance(), "Method"); }
内容的提问来源于stack exchange,提问作者purbarunc
相关产品推荐
相关产品推荐

