4

動機

私はSomeObject.javaファイルを持っています:

class SomeObject {
   String name;
}

コンパイルすると、バイトコードを含むSomeObject.classファイルが作成されます。

0xCAFEBABE...

JVM で SomeObject を使用すると、現在のクラスローダーによってロードされ、すべて正常に動作します。

ここで、動的コード生成が必要だと仮定しましょう。カスタム注釈を書くことができます

@Target(ElementType.TYPE)
public @interface Data {
   ...
}

クラス宣言に修飾子として追加します。

@Data
class SomeObject {
   String name;
}

ランタイム用に保持することもできます@Retention(RetentionPolicy.RUNTIME):

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Data {
   ...
}

質問

バイトコード インジェクションに使用される注釈はどこにありますか? 次の図のように、適切な実行時保持アノテーションを使用してクラスをロードするときに、クラスローダーはバイトコードを挿入しますか?

source -(compile)-> bytecode -(classloader bytecode injection)-> injected bytecode -(classloading)-> JVM loaded bytecode   
4

1 に答える 1

6

はい、カスタムクラスローダーでクラスをロードし、 JavassistASMなどのバイトコード操作ツールを使用して変更を実行し、クラスファイルのバイトコードではなく変更されたバイトコードをメモリにロードすることができます。それを行うためのより簡単な(そして私の意見ではより良い)方法がありますが。

注釈プロセッサツール(APT)

Java 6以降、コンパイルプロセスにフックできるAPT-processorがあります( javacの引数を介して)。APTを使用すると、コードのAST(抽象構文木)にアクセスでき、 javax.lang.modelを使用してコンパイルするときに直接変更を実行できます。これは、クラスファイルが必要な変更を加えて生成されることを意味します。

この場合、チェーンは次のようになります。

source -(compile and performs modifications at model level)-> bytecode already modified - regular class loader -> loads class into memory

コンパイル後の処理

使用できる別のアプローチは、コンパイル後のプロセスとして、コンパイル後にバイトコードインジェクションを実行することです。この場合、バイトコード変更ツール(ここでもjavassist、asmなど)を使用します。このツールは、目的のアノテーションが見つかったときに必要な変更を実行し、挿入されたバイトコードを使用して新しいクラスファイルを生成します。

そのような場合、チェーンは次のようになります。

source -compile -> bytecode -post-compile-> modified bytecode - regular class loader -> loads class into memory

ランタイムの変更

最後に、実行時のバイトコードの変更に到達します。あなたのアイデアは可能ですが、私の意見では、クラスローダーの魔法を残し、Javassistなどのツールを使用します。このツールを使用すると、変更および再ロードできる動的プロキシを使用することもできます。

javassistの特定のケースでは、チェーンは

source -compile -> bytecode -post-compile-> modified bytecode - regular class loader -> loaded into memory - javassist proxy -> modified class - javassist hot swapper -> re-modified class

ただし、プロキシは完全ではありません(まあ何も完璧ではありません)。パフォーマンスが低下し、クラスのパブリックインターフェイスを変更できなくなります(補足:APTとコンパイル後のプロセスの両方でクラスのパブリックインターフェイスを変更できます)。これについてもう少し詳しく説明することもできますが、これはすでにあなたに思考の糧を与えるのに十分な情報だと思います。追加情報が必要な場合は、コメントを残してください。

于 2013-03-07T13:22:16.687 に答える