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 を使用して、代替の doSomething() メソッドを生成するために使用する ASM バイト コード命令を確認しました。
誰かが ASM を知っているなら、あなたの助けは大歓迎です?
乾杯
ジョン