2

メソッドのエントリ/終了を記録するために、アタッチ API を介して動的にロードされる Java エージェント ライブラリを作成して、いくつかのメソッド (特定のスレッドのスタック トレースに表示されるメソッド) を再変換しようとしています。次に、メソッドの入口/出口情報が custom を介してエクスポートされますMBean

私の現在の「プロトタイプ」は、インストルメント化されたメソッドがネイティブでない限り、これまでのところ機能します。

java.lang.instrument.Instrumentation#setNativeMethodPrefix()のドキュメントによると、Java エージェントはネイティブ メソッドを非ネイティブ スタブ メソッドに置き換え、名前にその接頭辞を持つ別のネイティブ メソッドを追加できるはずです。元のネイティブ メソッドのネイティブ コードにバインドされます。

ただし、これを実装すると、次のエラーが発生します。

java.lang.UnsupportedOperationException: class redefinition failed: attempted to add a method

新しいネイティブ メソッドを追加したので、これは正しいことです。

ネイティブ メソッドを非ネイティブ メソッドに置き換えるだけで機能しますが、元のネイティブ メソッドにコールバックを委譲することはできません。nativeMethodClassSuffixネイティブメソッドはクラス名とメソッド名で検索され、類似のものがないため、別のクラスでネイティブメソッドを定義しても機能しません。別の新しいクラスローダーで同じ名前の別のクラスを定義することはうまくいくでしょう。新しいクラスへの呼び出しを委譲する間接的な方法で可能かもしれないと思いますが、1 つのネイティブ ライブラリは、1 つのみのクラスによってロードされたネイティブ メソッドにのみリンクできます。クラスローダが含まれているため、ネイティブ メソッドが適切にリンクされません。

ここで私が見逃している明らかなものはありますか?私のコードは少し長すぎてここに投稿できません。問題を示す Java エージェントの小さなサンプルを作成して、ここにリンクすることが役立つと思われる場合は、こちらを参照してください。

4

1 に答える 1

2

ここで私が見逃している明らかなものはありますか?私のコードは少し長すぎてここに投稿できません。問題を示す Java エージェントの小さなサンプルを作成して、ここにリンクすることが役立つと思われる場合は、こちらを参照してください。

いいえ。ネイティブ メソッドをマスクすると、JNI から呼び出す方法がなくなります。ネイティブ コードを使用してメソッドを呼び出す必要があります。(それが何かはわかりませんが、それが不可能だったら驚くでしょう)

もう 1 つのオプションは、マスク アウトするのではなく、ネイティブ メソッドへのすべての参照を変更することです。そうすれば、選択したときに元のメソッドを呼び出すことができます。

于 2012-12-19T14:27:22.420 に答える