先日、同僚がBCELを教えてくれました。これは、彼の説明と簡単な説明からわかるように、実行時にバイトコードを変更する方法です。私の最初の考えはそれが危険に聞こえるということでした、そして私の2番目の考えはそれがクールに聞こえるということでした。それから私はそれをもう少し考えて、モンキーパッチに関するコーディングホラーの投稿を思い出し、これが基本的に同じことであることに気づきました。誰かが実用的な何かのためにBCELを使用したことがありますか?これは基本的に実行時のモンキーパッチであるというのは正しいですか、それとも何かが足りないのでしょうか?
5 に答える
BCEL の FAQ から:
Q: BCEL を使用してクラスを動的に作成または変更できますか?
A: BCEL の util パッケージには、ClassLoader と JavaWrapper という便利なクラスが含まれています。ProxyCreator の例を見てください。
しかし、モンキーパッチは... うーん... 物議をかもしています。言語がサポートしていない場合は、おそらく使用しないでください。
良いユースケースがあれば、Jython を埋め込むことをお勧めしますか?
これは、従来のモンキー パッチ適用よりも少し低レベルであり、私が読んだところによると、VM に既に読み込まれているクラスは更新されません。ランタイム クラスの変更ではなく、クラス ファイルへの再保存のみをサポートします。
あなたはそれをモンキーパッチとして見るかもしれません。私はそれを使用したくない(多分私はそれの良いユースケースに直面したことがないのだろうか?)が、それをよく知っている(SpringとHibenrateがそれをどのように使用するのか、そしてその理由を知るために)。
BCEL はモンキー パッチをサポートしていません。バイトコードで操作し、場合によってはカスタム クラスローダーにロードするだけです。ただし、BCEL や Java エージェントなどのライブラリを使用して、JVM にモンキーパッチを実装できます。Java エージェント (-javaagent 引数によってロードされる) は、インストルメンテーション API にアクセスし、ロードされたクラスを変更できます。一部のブリッジを介して実装することは難しくありません。
でも覚えておいて:
- -javaagent を使用する必要があるかどうかはわかりません。
- どの言語でも、モンキー パッチを適用すると、予測不可能な動作が発生する可能性があります。
- メソッドを変更できます。理論的には、いくつかのメソッドを追加することもできますが、変更された (パッチが適用された) クラスに対してプロジェクトをコンパイルする必要があります。これは多くの痛みを引き起こすと思いますし、それだけの価値はありません。それをサポートする代替言語 (Groovy など) や、同様のもの (Scala での暗黙的な変換など) をサポートする代替言語があります。
- モンキー パッチを使用するよりも、API を適切に設計することをお勧めします。サードパーティのライブラリにはかなり役立つかもしれません。
この実際の例を参照してください: Jawk - Compiler Module。BCEL はカスタム言語の「コンパイル」に役立ちます。