7

乗算用の LDC 命令を変換する MethodVisitor を作成したいと考えています。

バイトコードの例:

ldc #26
imul

これは基本的に定数をプッシュしてから乗算します。

最初にそれが乗算用であることを確認する必要があるため、ステートフルな変換である必要があります。そうである場合は、ldc 命令に戻って定数を変更する必要があります。どうすればいいのかよくわかりませんし、定数を変更する方法もわかりません (別の値を渡そうとすると、古い値がまだ定数プールに残っていました)。

編集:

public class AdditionTransformer extends MethodAdapter {
    boolean replace = false;
    int operand = 0;

    AdditionTransformer(MethodVisitor mv) {
        super(mv);
    }

    @Override
    public void visitInsn(int opcode) {
        if (opcode == IMUL && replace) {
            operand *= 2;
            visitLdcInsn(operand);
            replace = false;
        }
        mv.visitInsn(opcode);
    }

    @Override
    public void visitLdcInsn(Object cst) {
        if (cst instanceof Integer && !replace) {
            operand = (Integer) cst;
            replace = true;
        } else {
            mv.visitLdcInsn(cst);
        }
    }
}

これは私が持っているものですが、定数プールの古い値は削除されず、バグがある可能性があります。

4

2 に答える 2

1

あなたが持っているものはほぼ正しいですが、ldc の後に呼び出される他のタイプのオペコードには対応していません。そこに(ldcにアクセスしなかったため)。既存の定数を削除するかどうかはよくわかりませんが、次のように定数を置き換えることができます。

@Override
public void visitInsn(int opcode) {
    if (opcode == IMUL && replace) {
        operand *= 2;
        mv.visitInsn(POP);
        mv.visitLdcInsn(operand);
        replace = false;
    }
    mv.visitInsn(opcode);
}

@Override
public void visitLdcInsn(Object cst) {
    if (cst instanceof Integer && !replace) {
        operand = (Integer) cst;
        replace = true;
    }
    mv.visitLdcInsn(cst);
}    

つまり、常に「ldc」にアクセスしてください。その後、IMUL がそれを処理しているのを確認した場合は、スタックをポップし、新しい定数を挿入してから、IMUL オペコードにアクセスします。ldc にアクセスした後、IMUL の前に他のメソッドにアクセスした場合に備えて、これを完全に安全にするために少し作業を行う必要があります。偏執的になるには、すべての訪問者メソッドをオーバーライドできます。それが visitInsn または IMUL でない場合は、ldc にアクセスして replace = false に設定します。

定数を完全に置き換えるのは、もう少し注意が必要です。これまでにクラスでアクセスしたすべてのメソッドでどの定数が表示されたかを覚えておく必要があります。これまでにその定数を見たことがない場合は、ldc にアクセスするときに値を置き換えることができます。

于 2010-12-21T13:20:17.680 に答える
1

このような方法でバイトコードを変更することに関心がある場合は、ASM ツリー APIを調べてください。使用しようとしている SAX スタイルのビジター インターフェイスではなく、より快適な DOM スタイルのツリー インターフェイスを使用して、LdcInsnNode.cst を簡単に置き換えることができます。

于 2011-01-26T23:57:07.213 に答える