bytebuddy拦截方法中使用Methodcall有没有办法调用带字段的变长参数方法?
Is there a way to call a variable length parameter method with a field using Methodcall in bytebuddy intercept method?
我正在尝试 return 使用 bytebuddy 将某些字段作为列表。我使用 MethodCall 调用了 Arrays.asList(),但它无法处理可变长度参数。还有其他方法吗?
public class TestClass {
int a;
int b;
public List<?> getFields(){
throw new RuntimeException("Bytebuddy not work.");
}
}
new ByteBuddy()
.rebase(TypePool.Default.ofSystemLoader().describe("com.test.TestClass").resolve(),
ClassFileLocator.ForClassLoader.ofSystemLoader())
.method(ElementMatchers.named("getFields"))
.intercept(MethodCall.invoke(Arrays.class.getMethod("asList", Object[].class))
.withField("a", "b"))
.make()
.load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
TestClass testTarget = new TestClass();
LOG.info("result : {}", testTarget.getFields());
错误:
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.IllegalStateException: public static java.util.List java.util.Arrays.asList(java.lang.Object[]) does not accept 2 arguments
at net.bytebuddy.implementation.MethodCall$Appender.toStackManipulation(MethodCall.java:3537)
at net.bytebuddy.implementation.MethodCall$Appender.apply(MethodCall.java:3506)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:708)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:693)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:600)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor.onVisitEnd(TypeWriter.java:5022)
at net.bytebuddy.utility.visitor.MetadataAwareClassVisitor.visitEnd(MetadataAwareClassVisitor.java:323)
at net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:722)
at net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:401)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining.create(TypeWriter.java:3827)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:2166)
at net.bytebuddy.dynamic.scaffold.inline.RebaseDynamicTypeBuilder.make(RebaseDynamicTypeBuilder.java:252)
at net.bytebuddy.dynamic.scaffold.inline.AbstractInliningDynamicTypeBuilder.make(AbstractInliningDynamicTypeBuilder.java:123)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3595)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:3819)
at
在这种更复杂的方法体的情况下,我建议您在 Java 中编写代码并使用 MethodDelegation
或 Advice
来解决问题代码,然后 link 你的方法。
或者,您可以使用 StackManipulation
并从单个代码块构建方法。在这种情况下,您需要先构造一个数组,然后将此数组提供给方法,因为可变参数在字节代码级别不存在。
我正在尝试 return 使用 bytebuddy 将某些字段作为列表。我使用 MethodCall 调用了 Arrays.asList(),但它无法处理可变长度参数。还有其他方法吗?
public class TestClass {
int a;
int b;
public List<?> getFields(){
throw new RuntimeException("Bytebuddy not work.");
}
}
new ByteBuddy()
.rebase(TypePool.Default.ofSystemLoader().describe("com.test.TestClass").resolve(),
ClassFileLocator.ForClassLoader.ofSystemLoader())
.method(ElementMatchers.named("getFields"))
.intercept(MethodCall.invoke(Arrays.class.getMethod("asList", Object[].class))
.withField("a", "b"))
.make()
.load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
TestClass testTarget = new TestClass();
LOG.info("result : {}", testTarget.getFields());
错误:
Exception in thread "main" java.lang.ExceptionInInitializerError Caused by: java.lang.IllegalStateException: public static java.util.List java.util.Arrays.asList(java.lang.Object[]) does not accept 2 arguments at net.bytebuddy.implementation.MethodCall$Appender.toStackManipulation(MethodCall.java:3537) at net.bytebuddy.implementation.MethodCall$Appender.apply(MethodCall.java:3506) at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:708) at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:693) at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:600) at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor.onVisitEnd(TypeWriter.java:5022) at net.bytebuddy.utility.visitor.MetadataAwareClassVisitor.visitEnd(MetadataAwareClassVisitor.java:323) at net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:722) at net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:401) at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining.create(TypeWriter.java:3827) at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:2166) at net.bytebuddy.dynamic.scaffold.inline.RebaseDynamicTypeBuilder.make(RebaseDynamicTypeBuilder.java:252) at net.bytebuddy.dynamic.scaffold.inline.AbstractInliningDynamicTypeBuilder.make(AbstractInliningDynamicTypeBuilder.java:123) at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3595) at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:3819) at
在这种更复杂的方法体的情况下,我建议您在 Java 中编写代码并使用 MethodDelegation
或 Advice
来解决问题代码,然后 link 你的方法。
或者,您可以使用 StackManipulation
并从单个代码块构建方法。在这种情况下,您需要先构造一个数组,然后将此数组提供给方法,因为可变参数在字节代码级别不存在。