【发布时间】:2020-06-13 16:57:47
【问题描述】:
bytebuddy的高级api和asm的低级api可以结合起来吗?
我想通过 bytebuddy 生成一个类、它的字段、注释和一些通用方法,例如 getter setter,因为它比 asm 容易得多。
然后我需要实现一个抽象类,在其中我需要使用 bytebuddy 似乎不支持的功能,例如条件、分支、在编译时调用具有未知数量参数的其他方法等。
我偶然发现了net.bytebuddy.implementation.bytecode.ByteCodeAppender 一个公开 MethodVisitor 的类,但我找不到任何如何正确使用它的示例。
new ByteBuddy()
.subclass(Base.class)
.name(className)
... define fields ...
.defineMethod("testFor", Result.class, Ownership.MEMBER, Visibility.PUBLIC) //testFor is an abstract method on superclass that i inherit from - public abstract Result testFor(Context c, WEnvironment env)
.withParameters(Context.class, WEnvironment.class)
.intercept(MethodDelegation.to(new ByteCodeAppenderImpl(...some ctr args...)));
class ByteCodeAppenderImpl implements ByteCodeAppender {
<...ctr...>
@Override
public Size apply(MethodVisitor mv, Implementation.Context implContext, MethodDescription insnMethod) {
mv.visitCode();
mv.visitVarInsn(...);
mv.visitFieldInsn(..)
//Here i do required asm calls to implement the method
....
StackManipulation.Size operandStackSize = new StackManipulation.Compound().apply(methodVisitor, implementationContext);
return new Size(operandStackSize.getMaximalSize(), instrumentedMethod.getStackSize());
}
通过这样做我得到一个异常:
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 net.bytebuddy.implementation.bytecode.ByteCodeAppender$Size my.playground.BytebuddyPlayground08$ByteCodeAppenderImpl .apply(net.bytebuddy.jar.asm.MethodVisitor,net.bytebuddy.implementation.Implementation$Context,net.bytebuddy.description.method.MethodDescription)] allows for delegation from public my.playground.Result my.playground.Custom1592066531191.testFor(my.playground.Context,my.playground.WEnvironment)
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 net.bytebuddy.implementation.bytecode.ByteCodeAppender$Size my.playground.BytebuddyPlayground08$ByteCodeAppenderImpl .apply(net.bytebuddy.jar.asm.MethodVisitor,net.bytebuddy.implementation.Implementation$Context,net.bytebuddy.description.method.MethodDescription)] allows for delegation from public my.playground.Result my.playground.Custom1592066531191.testFor(my.playground.Context,my.playground.WEnvironment)
at net.bytebuddy.implementation.bind.MethodDelegationBinder$Processor.bind(MethodDelegationBinder.java:1096)
at net.bytebuddy.implementation.MethodDelegation$Appender.apply(MethodDelegation.java:1282)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:713)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:698)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:605)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:5133)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1933)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:225)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:198)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3404)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:3600)
我要继承的 Base.class,以及我想要实现的方法
public abstract class Base<T extends WEnvironment> extends ContextTest {
public abstract Result testFor(Context c, T t);
}
【问题讨论】:
标签: java java-bytecode-asm byte-buddy