public interface ClassFileTransformer
redefined
またはretransformed
がロードされたときにトランスフォーマtransform
メソッドが呼び出されるように、addTransformer
メソッドを使用してこのインタフェースの実装を登録します。 実装は、ここで定義されたtransform
メソッドの1つを上書きする必要があります。 トランスフォーマは、クラスがJava仮想マシンによって定義される前に呼び出されます。
Instrumentation.addTransformer(ClassFileTransformer,boolean)
のcanRetransform
パラメータに応じて2種類のトランスフォーマがあります。
- trueとして
canRetransform
に追加された再変換可能トランスフォーマ - falseとして
canRetransform
に追加された、またはInstrumentation.addTransformer(ClassFileTransformer)
に追加された、再変換不可能トランスフォーマ
トランスフォーマがaddTransformer
で登録されると、トランスフォーマは、新しいクラス定義とクラス再定義のたびに呼び出されます。 再変換可能トランスフォーマは、クラスの再変換のたびにも呼び出されます。 新しいクラス定義の要求は、ClassLoader.defineClass
またはこのネイティブの同等のものを使って行われます。 クラス再定義の要求は、Instrumentation.redefineClasses
またはこのネイティブの同等のものを使って行われます。 クラス再変換の要求は、Instrumentation.retransformClasses
またはこのネイティブの同等のものを使って行われます。 トランスフォーマは、クラス・ファイル・バイトが確認または適用される前に、要求の処理中に呼び出されます。 複数のトランスフォーマが存在する場合、変換はtransform
呼出しのチェーンによって構成されます。 つまり、transform
の呼出しによって返されるバイト配列は、classfileBuffer
パラメータを介して、その次の呼出しの入力になります。
変換は次の順序で適用されます。
- 再変換不可能トランスフォーマ
- 再変換不可能ネイティブ・トランスフォーマ
- 再変換可能トランスフォーマ
- 再変換可能ネイティブ・トランスフォーマ
再変換では、再変換不可能トランスフォーマは呼び出されず、直前の変換結果が再利用されます。 それ以外の場合は、このメソッドが呼び出されます。 トランスフォーマのそれぞれの種類内では、登録された順序でトランスフォーマが呼び出されます。 ネイティブ・トランスフォーマはJava仮想マシン・ツール・インタフェースのClassFileLoadHook
イベントで提供されます。
最初のトランスフォーマへの入力は、classfileBuffer
パラメータを介して渡され、次のようになります。
- 新しいクラス定義の場合は、
ClassLoader.defineClass
に渡されるバイト - クラス再定義の場合は、
definitions.getDefinitionClassFile()
。ここで、definitions
はInstrumentation.redefineClasses
のパラメータ - クラス再変換の場合は、新しいクラス定義に渡されるバイト。再定義された場合は最新の再定義。いずれの場合も、再変換不可能トランスフォーマによって行われるすべての変換がそのまま自動的に再適用され、不変である。詳細については、
Instrumentation.retransformClasses
を参照
実装しているメソッドが変換不要と判定すると、メソッドはnull
を返します。 変換が必要と判定すると、メソッドは新しいbyte[]
配列を作成し、すべての必要な変換とともにclassfileBuffer
入力をその配列の中にコピーし、新しい配列を返します。 classfileBuffer
入力は変更されません。
再変換と再定義のケースでは、トランスフォーマは、再定義セマンティックスをサポートしなければいけません。初期定義中にトランスフォーマが変更したクラスがあとで再変換または再定義される場合、トランスフォーマは、2番目のクラスの出力クラス・ファイルで最初の出力クラス・ファイルが正当に再定義されていることを確認しなければいけません。
トランスフォーマがキャッチしない例外をスローする場合は、それ以降もトランスフォーマが呼び出され、ロードや再定義が試行されます。 このため、例外をスローすることはnull
を返すことと同じになります。 非チェック例外がトランスフォーマ・コードで生成されるときに予期しない動作が起こらないようにするため、トランスフォーマはThrowable
をキャッチすることができます。 classFileBuffer
が有効にフォーマットされたクラス・ファイルを表さないとトランスフォーマが判定した場合、トランスフォーマはIllegalClassFormatException
をスローする必要があります。これにはnullを返すのと同じ効果がありますが、形式の不備についてのログの作成やデバッグを容易にします。
「クラス・ファイル」という用語は、「Java Virtual Machine仕様」の3.1の項で定義されているように、ファイルに存在するかどうかに関係なく、クラス・ファイル形式の一連のバイトを意味します。
- 導入されたバージョン:
- 1.5
- 関連項目:
Instrumentation
-
メソッドのサマリー
修飾子と型 メソッド 説明 default byte[]
transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
指定されたクラス・ファイルを変換し、新しい置換クラス・ファイルを返します。default byte[]
transform(Module module, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
指定されたクラス・ファイルを変換し、新しい置換クラス・ファイルを返します。
-
メソッドの詳細
-
transform
default byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException- 実装要件:
- デフォルト実装はnullを返します。
- パラメータ:
loader
- 変換されるクラスを定義しているローダー。ブートストラップ・ローダーの場合はnull
className
- 『Java仮想マシン仕様』で定義されている完全指定クラスの内部形式のクラス名とインタフェース名。 たとえば、"java/util/List"
です。classBeingRedefined
- 再定義または再変換によってトリガーされた場合は、再定義または再変換されているクラス。これがクラス・ロードの場合は、null
protectionDomain
- 定義または再定義されているクラスの保護領域classfileBuffer
- クラス・ファイル形式の入力バイト・バッファ(変更されてはならない)- 戻り値:
- 整形式のクラス・ファイル・バッファ(変換の結果)、変換されなかった場合は
null
- 例外:
IllegalClassFormatException
- 入力が整形式のクラス・ファイルを表さない場合
-
transform
default byte[] transform(Module module, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException指定されたクラス・ファイルを変換し、新しい置換クラス・ファイルを返します。- 実装要件:
- このメソッドのデフォルトの実装では、
transform
メソッドが呼び出されます。 - パラメータ:
module
- 変換されるクラスのモジュールloader
- 変換されるクラスを定義しているローダー。ブートストラップ・ローダーの場合はnull
className
- 『Java仮想マシン仕様』で定義されている完全指定クラスの内部形式のクラス名とインタフェース名。 たとえば、"java/util/List"
です。classBeingRedefined
- 再定義または再変換によってトリガーされた場合は、再定義または再変換されているクラス。これがクラス・ロードの場合は、null
protectionDomain
- 定義または再定義されているクラスの保護領域classfileBuffer
- クラス・ファイル形式の入力バイト・バッファ(変更されてはならない)- 戻り値:
- 整形式のクラス・ファイル・バッファ(変換の結果)、変換されなかった場合は
null
- 例外:
IllegalClassFormatException
- 入力が整形式のクラス・ファイルを表さない場合- 導入されたバージョン:
- 9
-