0

特定の命令の前に呼び出しを挿入してメソッドを変更しようとしています。私のインストルメンテーションは、bcel パッケージ自体によって自動生成できない別のスタックマップ テーブルになるようです。そのため、インストルメント化されたクラス ファイルに古いスタックマップ テーブルが含まれているため、jvm でエラーが発生します。すべてのコード属性を削除できる MethodGen のメソッドである removeCodeAttributes を試しました。たとえば、ラップされた関数など、単純なケースで機能します。そして、今の私の場合はうまくいきません。

public class Insert{
    public static void main(String[] args) throws ClassFormatException, IOException{
        Insert isrt = new Insert();
        String className = "StringBuilder.class";
        JavaClass jclzz = new ClassParser(className).parse();
        ClassGen cgen = new ClassGen(jclzz);
        ConstantPoolGen cpgen = cgen.getConstantPool();
        MethodGen mgen = new MethodGen(jclzz.getMethods()[1], className, cpgen);
        InstructionFactory ifac = new InstructionFactory(cgen);
        InstructionList ilist = mgen.getInstructionList();
        for (InstructionHandle ihandle : ilist.getInstructionHandles()){
            System.out.println(ihandle.toString());
        }
        InstructionFinder f = new InstructionFinder(ilist);
        InstructionHandle[] insert_pos = (InstructionHandle[])(f.search("invokevirtual").next());
        Instruction inserted_inst = ifac.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC);
        System.out.println(inserted_inst.toString());
        ilist.insert(insert_pos[0], inserted_inst);


        mgen.setMaxStack();
        mgen.setMaxLocals();


        mgen.removeCodeAttributes();
        cgen.replaceMethod(jclzz.getMethods()[1], mgen.getMethod());

        ilist.dispose();
        //output the file
        FileOutputStream fos = new FileOutputStream(className);
        cgen.getJavaClass().dump(fos);
        fos.close();
    }
}
4

1 に答える 1

2

を削除することStackMapTableは、間違った を修正するための適切な解決策ではありませんStackMapTable。重要な引用は次のとおりです。

4.7.4. StackMapTable 属性

classバージョン番号が 50.0 以上のファイルでは、メソッドのCode属性に属性がない場合StackMapTable暗黙のスタック マップ属性があります( §4.10.1 )。この暗黙的なスタック マップ属性は、ゼロに等しいStackMapTable属性と同等です。number_of_entries

StackMapTableにはすべてのブランチ ターゲットに対して明示的なエントリが必要なため、このような暗黙的なStackMapTableメソッドはブランチのないメソッドでのみ機能します。ただし、これらの場合、メソッドには通常明示的なものStackMapTableがないため、その問題は発生しません (インストルメンテーションによって削除されたブランチがメソッドに含まれていない限り)。

もう 1 つの結論はStackMapTable、クラス ファイルのバージョン番号 50. もちろん、これは、バージョン以降で導入されたクラス ファイル機能が必要ない場合の解決策にすぎません50…</p>

StackMapTableツールのサポートが最新ではない、あなたのようなシナリオのために、壊れた s を持つクラス ファイルのフォールバック モードを JVM がサポートする猶予期間がありました。(-XX:+FailoverToOldVerifierまたはを参照-XX:-UseSplitVerifier) しかし、猶予期間は終了し、そのサポートは拒否されました。つまり、Java 8 JVM はフォールバック モードをサポートしなくなりました。

これらの新しいバージョンの機能を使用する可能性のある新しいクラス ファイルを実装し、Java の開発に遅れないようにしたい場合は、次の 2 つの選択肢しかありません。

  • StackMapTable手動で正確に計算する
  • StackMapTable属性の計算をサポートするツールを使用してくださいASM
于 2014-10-20T11:13:22.540 に答える