11

Javassistを使用して、ロード時にクラスを動的に操作しています。Javassist を使用するとメソッドにコードを追加するのは比較的簡単ですが、コードを削除する方法を見つけることができませんでした。

現時点では、nop命令を使用して対象のオペコードとパラメーターを置き換えることで、コードの削除をシミュレートしています。ただし、これはほとんどハックだと思います。

  • パラメータのバイト長が異なるため、各オペコードを個別に処理する必要があります。場合によっては、削除されたオペコードがスタックに影響を与えるかどうかに応じて、noppopのどちらかを選択する必要もあります。この種の操作は退屈になり始めており、それを行うコードはそれに応じて複雑になっています。したがって、当然、既存のソリューションを望んでいます。

  • 最終結果はnop命令で埋められます。JVM はパフォーマンスに影響を与えずにこれらを最適化する必要がありますが、結果のバイトコードは依然として非常に洗練されておらず、必要以上に大きくなっています。これは美学の問題ですが、それでも考慮すべき事項です。

残念ながら、バイトコード配列の一部をシフトしてギャップを埋めるだけでは十分ではありません。移動したコードへの参照 (分岐命令インデックスなど) もすべて更新する必要があります。

Javassist を使用して命令を削除することは可能ですか? あるいは、基本的に自分でバイトコードを解析しなくても、簡単にそれを行うことができるバイトコード操作ライブラリはありますか?

4

2 に答える 2

3

Apache BCELでは、命令を削除できます。

命令の削除も非常に簡単です。すべての命令ハンドルと、指定された範囲内に含まれる命令が命令リストから削除され、破棄されます。ただし、delete() メソッドは、削除された命令の 1 つをまだ参照している命令ターゲッターがある場合、TargetLostException をスローすることがあります。ユーザーは、try-catch 句でこのような例外を処理し、これらの参照を別の場所にリダイレクトする必要があります。

マニュアルにも例があります。

于 2012-02-10T13:50:12.820 に答える
0

javassist チュートリアルから:

Javassist では、メソッドまたはフィールドを削除することはできませんが、名前を変更することはできます。そのため、メソッドが不要になった場合は、名前を変更し、CtMethod で宣言されている setName() と setModifiers() を呼び出してプライベート メソッドに変更する必要があります。

于 2012-02-13T03:23:28.490 に答える