gpt4 book ai didi

java - 使用 ASM 字节码修改库验证实现方法代理的错误

转载 作者:行者123 更新时间:2023-11-29 09:09:14 25 4
gpt4 key购买 nike

我在使用 ASM 字节代码库创建代理方法时遇到困难。

我想转换以下代码:

public ReturnType doSomething( ParameterOne parameterOne, 
ParameterTwo parameterTwo ){

ReturnType returnType = new ReturnType();
returnType.setDataOne( parameterOne.getDataOne() );
returnType.setDataTwo( parameterTwo.getDataTwo() );
return returnType;
}

到:

public ReturnType copyOff_doSomething( ParameterOne parameterOne, 
ParameterTwo parameterTwo ){

ReturnType returnType = new ReturnType();
returnType.setDataOne( parameterOne.getDataOne() );
returnType.setDataTwo( parameterTwo.getDataTwo() );
return returnType;
}

public ReturnType doSomething( ParameterOne parameterOne,
ParameterTwo parameterTwo ){

return copyOff_doSomething( parameterOne, parameterTwo );
}

要创建 copyOff_doSomething() 方法,我使用以下代码:

public MethodVisitor visitMethod( int access, String name, String desc, 
String signature, String[] exceptions ) {

System.out.println(
"access= " + access + ", name = " + name + ", desc = " +
desc + ", signature = " + signature );

if ( name.equals( "doSomething" ) ){

MethodVisitor methodVisitor =
super.visitMethod( access, "copyOff_" + name, desc,
signature, exceptions );

return methodVisitor;
}
else {
return super.visitMethod( access, name, desc, signature, exceptions );
}
}

上面的代码有效地删除了原始的 doSomething() 方法并将其连同其代码主体复制到 copyOff_doSomething()。

我在生成替换 doSomething() 方法时出现问题:

@Override
public void visitEnd() {

MethodVisitor mv = super.visitMethod( ACC_PUBLIC, "doSomething",
"(Lcom/javaspeak/classloader/tests/proxymethod/ParameterOne;" +
"Lcom/javaspeak/classloader/tests/proxymethod/ParameterTwo;)" +
"Lcom/javaspeak/classloader/tests/proxymethod/ReturnType;",
null, null );

mv.visitCode();
Label l0 = new Label();
mv.visitLabel( l0 );
mv.visitLineNumber( 18, l0 );
mv.visitVarInsn( ALOAD, 0 );
mv.visitVarInsn( ALOAD, 1 );
mv.visitVarInsn( ALOAD, 2 );

mv.visitMethodInsn( INVOKEVIRTUAL,
"com/javaspeak/classloader/tests/proxymethod/FinalMethod",
"copyOff_doSomething",
"(Lcom/javaspeak/classloader/tests/proxymethod/ParameterOne;" +
"Lcom/javaspeak/classloader/tests/proxymethod/ParameterTwo;)" +
"Lcom/javaspeak/classloader/tests/proxymethod/ReturnType;");

mv.visitInsn( ARETURN );
Label l1 = new Label();
mv.visitLabel( l1 );

mv.visitLocalVariable( "this",
"Lcom/javaspeak/classloader/tests/proxymethod/FinalMethod;",
null, l0, l1, 0 );

mv.visitLocalVariable( "parameterOne",
"Lcom/javaspeak/classloader/tests/proxymethod/ParameterOne;",
null, l0, l1, 1 );

mv.visitLocalVariable( "parameterTwo",
"Lcom/javaspeak/classloader/tests/proxymethod/ParameterTwo;",
null, l0, l1, 2 );

mv.visitMaxs( 3, 3 );
mv.visitEnd();
super.visitEnd();
}

问题是我收到以下错误:

java.lang.VerifyError: Bad type on operand stack in method 
com.javaspeak.classloader.tests.proxymethod.ProxyMethod.doSomething(
Lcom/javaspeak/classloader/tests/proxymethod/ParameterOne;
Lcom/javaspeak/classloader/tests/proxymethod/ParameterTwo;)
Lcom/javaspeak/classloader/tests/proxymethod/ReturnType; at offset 3

我不知道错误是什么意思以及如何修复错误。如上所述,我使用 ASMfier 生成替换 doSomething() 方法的代码。

我的策略是使用 visitMethod 方法将 doSomething() 重命名为 copyOff_doSomething(),然后使用 visitEnd() 方法从头开始生成调用 copyOff_doSomething() 方法的新替代 doSomething() 方法。

也许 ASM 不适合我的策略,我应该换一种方式?

也许我需要修改 ASMfier 为替换 doSomething() 方法生成的代码。我对生成的代码的理解不是很好。

我正在使用 JDK 1.7 和 ASM 4.0。我使用 ASMfier 查看使用哪些 ASM 字节码指令来生成替换 doSomething() 方法。

如果有人知道 ASM,您的帮助将不胜感激?

干杯

约翰

最佳答案

很可能是 owner参数(在您的示例中硬编码为 com/javaspeak/classloader/tests/proxymethod/FinalMethod)与 this 的实际类型不匹配.所以,你的适配器应该使用 name来自 ClassVisitor.visit(..) 的值打电话。

另请参阅我的 AOSD'07 中的“替换方法体”部分论文“使用 ASM 框架实现常见的字节码转换模式”。

关于java - 使用 ASM 字节码修改库验证实现方法代理的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13253400/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com