私の目標は、一部の Java バイトコードのすべての基本ブロックの先頭に少量のコードを実装することです。目的は、基本ブロックの実行パスを記録することです。現在、Javassist を使用してメソッドの最初と最後にいくつかのコードを計測していますが、より細かいバイトコードの場所を計測する際に Javassist API で壁にぶつかりました。
Javassist は、メソッド内のすべての基本ブロックを表す Block[] を提供してくれます。基本ブロックはバイトコードの場所を報告できるため、インストルメンテーションが必要な場所を把握できます。私が使用したかったJavassistのインストルメンテーションはCtMethod.insertAt(int sourceCodeLineNumber,String newSourceCode)でしたが、これはバイトコードの行番号ではなくソースコードの行番号を使用しているため、この質問に示されている問題が発生します(この時点でその問題を修正します)。
質問:変数自体が Javassist instrumentation からのものである場合、 instrumentation を使用してメソッド内の変数に値を割り当てるにはどうすればよいですか。できれば他のツールを使用する必要はありませんが、この時点で得られるあらゆる支援を受けています。
変数は、Javassist を使用して次のように宣言されます。
//m is a CtMethod
try { m.addLocalVariable("someVar", ClassPool.getDefault().get("SomePackage.SomeClass")); }
catch (NotFoundException e) { e.printStackTrace(); }
私の最悪のシナリオは、javassist が計測するスタック変数を推定し、メソッド/クラス全体を通過するイテレータを使用してバイトコードを挿入することですが、それは本当に厄介なことです。私のメソッドには整数入力 (ブロック ID) と void 出力しかないため、Java バイトコードはすべての基本ブロックの先頭で次のようになります。
ALOAD 6 //6 is my new Javassist variable ID, however I don't think I can get Javassist to actually tell it to me
ICONST_1 //My parameters, which is an int. I'd have to switch statement between ICONST, SIPUSH, and ALOAD depending on basic block's index size
INVOKEVIRTUAL SomePackage/SomeClass.SomeMethod(I)V