4

コンパイルされたクラスファイルを解析しながら、特定のクラスへの呼び出しをメソッド本体内の別のクラスへの呼び出しに置き換えたい...
または言い換えると、メソッド内の特定のクラスの使用を検出し、その部分だけを置き換える方法はありますか? javaassistのようなものを使用するメソッドの。

たとえば..私がコンパイルされたバージョンを持っていた場合

class A { public int m() { int i = 2; B.multiply(i,i); return i; } }

Bの使用を検出し、実行するコードを変更する方法はありますか

class A { public int m() { int i = 2; C.divide(i,i); return i; } }

別の方法として、使用するソースファイルをgrepするパーサーを作成することもできますが、リフレクションを使用して新しいコンパイル済みクラスファイルを生成するなど、より洗練されたソリューションをお勧めします。

何かご意見は ?

4

5 に答える 5

3

@djna が言うように、バイトコード ファイルをロードする前に変更することは可能ですが、おそらくこれを行いたくないでしょう。

  • コードの変更を行うコードは、複雑で保守が困難になる可能性があります。
  • 変更されたコードは、デバッグが困難になる可能性があります。まず、ソース レベル デバッガーは、実際に編集しているコードに対応しなくなったソース コードを表示します。

バイトコードの書き換えは、特定の場合に役立ちます。たとえば、JDO 実装は、バイトコードの書き換えを使用して、オブジェクト メンバーのフェッチを永続ライブラリへの呼び出しに置き換えます。ただし、これらのファイルのソース コードにアクセスできる場合は、ソース コードを前処理 (または生成) することで、より優れた (つまり、保守しやすい) ソリューションを得ることができます。

EDIT:そして、AOPまたはGroovyも実行可能な代替手段のように聞こえますが、予想される書き換えの程度によって異なります。

于 2009-08-11T07:05:26.753 に答える
2

BCELまたはASM

私は最近、Java クラス ファイルを読み取るためのライブラリをいくつか調べました。BCEL は最速であり、依存関係の数が最も少なく、すぐにコンパイルでき、非常にシンプルな API を備えていました。ASM にはより多くの依存関係があるため、私は ASM よりも BCEL を好みました (ただし、API はより単純であると言われています)。

前述のように、AspectJ は別の実行可能なオプションです。

BCEL は実にシンプルです。3 行のコードでメソッドのリストを取得できます。

ClassParser cp = new ClassParser( "A.class" );
JavaClass jc = cp.parse();
Method[] m = jc.getMethods();

メソッド内の命令を取得する方法など、さらにイントロスペクションを行うための API 機能は他にもあると思います。ただし、このソリューションは AspectJ よりも手間がかかる可能性があります。

もう 1 つの可能性は、演算を呼び出すコードのすべてのインスタンスを変更しようとするのではなく、乗算または除算のメソッド自体を変更することです。これは、BCEL (または ASM) を使用する方が簡単な方法です。

于 2009-08-11T09:15:40.667 に答える
1

コンパイルされたJavaのバイトコードの形式が指定されており、それを操作する製品が存在します。

このライブラリには、必要な機能があるようです。これらの変換を確実に行うことがどれほど簡単かはわかりません。

于 2009-08-11T05:32:27.050 に答える
1

Groovy を使用してもかまわない場合は、 への呼び出しをインターセプトしてB.multiply、 に置き換えることができますC.divideここで例を見つけることができます。

于 2009-08-11T07:11:18.270 に答える
0

これらの操作は、アプリケーションを起動する前にディスク上の実行可能ファイルを変更することで、事前に実行する方がはるかに簡単です。実行時にメモリ内のコードを操作すると、C/C++ でメモリ内のコードを操作するよりもエラーが発生しやすくなります。なぜこれを行う必要があるのですか?

于 2009-08-11T05:35:32.910 に答える