JVMI関数RetransformClassesとイベントフックClassLoadFileHookを使用してクラスを計測しようとするやや複雑なアーキテクチャがありますが、JNIを使用して変換を実行するにはJava空間に移動します。 ClassLoadFileHook
では、インストルメントしたいクラスに対してそれが実行されているかどうかを確認し、そうであれば、ASM 5.0.4を使用して計測を実行するJavaクラスにJNI呼び出しを行います。つまり、Javaの領域では、インストルメントされたクラスを表すバイト配列を取得してから、ネイティブコードを呼び出して更新を適用します。ASMバイトコード置換機能が完了していません
私が経験しています問題は、私はインスタンス化した後、私はクラスを再変換私のJavaコードで、コードは/中にハングしているということですClassReader
:
/**
* Transform some class and then call back down to native code to apply
* the transformation.
*
* @param existingClass The existing class to change.
*/
public synchronized void transformSomeClass(byte[] existingClass) {
System.out.println("Transformation function started. Existing class len: " + existingClass.length);
try {
ClassReader cr = new ClassReader(existingClass);
// No statements below here are being executed.
// I'm also not sure if `new ClassReader` is being successfully
// executed.
System.out.println("After ClassReader instantiation");
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
System.out.println("After ClassWriter instantiation");
ClassVisitor cv =
new MyCustomClassAdapter(cw, this.lineNumberToPlaceUpdate_);
System.out.println("After ClassVisitor instantiation");
cr.accept(cv, 0);
System.out.println("After cv accept.");
System.out.println("Applying class transformation natively.");
// Call back down to native code to apply the update in ClassLoadFileHook.
applyClassTransformNative(cw.toByteArray());
System.out.println("Transformation function ended.");
} catch (Exception e) {
// This is never being fired.
System.err.println("Class transformation could not be completed. Error message: " + e.getMessage());
e.printStackTrace();
} finally {
// This print statement is never executed.
System.err.println("Going back to native code from finally");
}
}
私はコードのコメントで言及したよう、intentiation文が実行された後は何もありません。 finally
ブロックさえ実行されません。私はここで何が起きているのかよく分かりません。なぜClassReader
が一般的なバイト配列を取ってインスタンス化すると、コードがこのようにハングアップするのですか?私は実際にそのクラスで何の操作も行っていない。
「new ClassReader」が戻ってこないかどうかわからない理由を知りたい人のための副作用として/私がデバッガを使用していない理由 - 私が作っているJNI呼び出しは、私が知る限り、デバッガを使用する贅沢はなく、Javaプロセスは単一のエージェントしか実行できません。私が間違っていると、なぜ誰かが理由を説明し、デバッガの使い方を教えてくれていることに感謝します。 – DIMMSum
ASMクラスをロードしているクラス・ローダーを暗黙的にロックするクラス・ロードをトリガーしているとします。したがって、あなたのコードは進展しません。それ以外の場合、あなたはあなたの出力を得るでしょう。 –
"Javaプロセスは単一のエージェントしか実行できません"?私はそのような制限について聞いたことがありません。私は確かにそれをテストし、複数のエージェントを実行しても問題はありませんでした... – Holger