JavaTM Platform
Standard Ed. 6

java.lang.instrument
インタフェース Instrumentation


public interface Instrumentation

このクラスは、Java プログラミング言語コードを計測するためのサービスを提供します。インストゥルメンテーションとは、ツールで使用するデータを収集することを目的としてメソッドにバイトコードを追加することです。変更は単に追加されるため、これらのツールはアプリケーションの状態や動作を変更しません。状態や動作に影響を及ぼさないこの種のツールには、監視エージェント、プロファイラ、カバレージアナライザ、およびイベントロガーなどがあります。

Instrumentation インタフェースのインスタンスを取得する方法は 2 つあります。

  1. エージェントクラスを指定する方法で JVM を起動した場合。この場合、Instrumentation インスタンスは、そのエージェントクラスの premain メソッドに渡されます。

  2. JVM の開始後にエージェントを開始する機構が JVM に用意されている場合。この場合、Instrumentation インスタンスは、そのエージェントコードの agentmain メソッドに渡されます。

これらの機構は、パッケージの仕様 で説明します。  

エージェントが Instrumentation インスタンスを取得すると、インスタンス上のメソッドをいつでも呼び出すことができます。

導入されたバージョン:
1.5

メソッドの概要
 void addTransformer(ClassFileTransformer transformer)
          提供されたトランスフォーマを登録します。
 void addTransformer(ClassFileTransformer transformer, boolean canRetransform)
          提供されたトランスフォーマを登録します。
 void appendToBootstrapClassLoaderSearch(JarFile jarfile)
          ブートストラップクラスローダーで定義されるインストゥルメンテーションクラスで JAR ファイルを指定します。
 void appendToSystemClassLoaderSearch(JarFile jarfile)
          システムクラスローダーで定義されるインストゥルメンテーションクラスで JAR ファイルを指定します。
 Class[] getAllLoadedClasses()
          JVM により現在ロードされているすべてのクラスの配列を返します。
 Class[] getInitiatedClasses(ClassLoader loader)
          loader が起動ローダーであるすべてのクラスの配列を返します。
 long getObjectSize(Object objectToSize)
          指定されたオブジェクトにより消費される記憶領域の容量の実装固有の近似値を返します。
 boolean isModifiableClass(Class<?> theClass)
          クラスが 再変換 または 再定義 で変更可能かどうかを判定します。
 boolean isNativeMethodPrefixSupported()
          現在の JVM 設定で ネイティブメソッドの接頭辞の設定をサポートしているかどうかを返します。
 boolean isRedefineClassesSupported()
          現在の JVM 構成がクラスの再定義をサポートしているかどうかを返します。
 boolean isRetransformClassesSupported()
          現在の JVM 構成がクラスの再変換をサポートしているかどうかを返します。
 void redefineClasses(ClassDefinition... definitions)
          提供されたクラスファイルを使って提供されたクラスのセットを再定義します。
 boolean removeTransformer(ClassFileTransformer transformer)
          提供されたトランスフォーマの登録を解除します。
 void retransformClasses(Class<?>... classes)
          指定されたクラスセットを再変換します。
 void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix)
          このメソッドは、名前に接頭辞を適用して再試行できるようにして、ネイティブメソッド解決のエラー処理を変更します。
 

メソッドの詳細

addTransformer

void addTransformer(ClassFileTransformer transformer,
                    boolean canRetransform)
提供されたトランスフォーマを登録します。これにより、登録されたトランスフォーマが依存するクラスの定義を除き、将来のすべてのクラス定義はトランスフォーマにより確認されます。トランスフォーマは、クラスが 再定義 の場合、または canRetransform が true ならばクラスが 再変換 の場合に、クラスのロード時に呼び出されます。変換が呼び出される順序については、ClassFileTransformer.transform を参照してください。トランスフォーマが実行中に例外をスローすると、JVM は登録されているその他のトランスフォーマを順に呼び出します。同じトランスフォーマを複数回追加することはできますが、そうするべきではありません。これを避けるには、トランスフォーマクラスの新しいインスタンスを作成してください。  

このメソッドは、class specification で記述されているように、インストゥルメンテーションで使用するものです。

パラメータ:
transformer - 登録するトランスフォーマ
canRetransform - このトランスフォーマの変換を再変換できるかどうか
例外:
NullPointerException - null トランスフォーマを渡した場合
UnsupportedOperationException - canRetransform が true であり、JVM の現在の設定が再変換 (isRetransformClassesSupported() が false) を許可しない場合
導入されたバージョン:
1.6

addTransformer

void addTransformer(ClassFileTransformer transformer)
提供されたトランスフォーマを登録します。  

addTransformer(transformer, false) と同じです。

パラメータ:
transformer - 登録するトランスフォーマ
例外:
NullPointerException - null トランスフォーマを渡した場合
関連項目:
addTransformer(ClassFileTransformer,boolean)

removeTransformer

boolean removeTransformer(ClassFileTransformer transformer)
提供されたトランスフォーマの登録を解除します。登録解除されたトランスフォーマは、将来クラス定義を確認できなくなります。直前に追加された一致するトランスフォーマのインスタンスを削除します。クラスローディングのマルチスレッド的性質により、削除されたあとでもトランスフォーマを呼び出すことができます。このような状況を考慮して、慎重にトランスフォーマを記述する必要があります。

パラメータ:
transformer - 登録を解除するトランスフォーマ
戻り値:
トランスフォーマが見つかり、削除された場合は true。 トランスフォーマが見つからなかった場合は false
例外:
NullPointerException - null トランスフォーマを渡した場合

isRetransformClassesSupported

boolean isRetransformClassesSupported()
現在の JVM 構成がクラスの再変換をサポートしているかどうかを返します。すでにロードされているクラスを再変換する機能は、JVM のオプションの機能です。再変換がサポートされるのは、エージェント JAR ファイルで Can-Retransform-Classes マニフェスト属性が true に設定されていて (package specification 参照)、かつ JVM がこの機能をサポートしている場合に限られます。単一の JVM の 1 つのインスタンス生成の間に、このメソッドに複数の呼び出しを行うと、常に同じ答えが返されます。

戻り値:
現在の JVM 構成がクラスの再変換をサポートする場合は true、サポートしない場合は false
導入されたバージョン:
1.6
関連項目:
retransformClasses(java.lang.Class...)

retransformClasses

void retransformClasses(Class<?>... classes)
                        throws UnmodifiableClassException
指定されたクラスセットを再変換します。

この機能は、すでにロード済みのクラスのインストゥルメンテーションを容易にします。クラスが最初にロードされたとき、またはクラスが 再定義 であるとき、初期クラスファイルバイトは ClassFileTransformer で変換できます。この関数は、変換が以前行われたかどうかには関係なく、変換処理を再実行します。この再変換は次の手順で行われます。

変換の順序については、変換 メソッドで説明しています。再変換不可能トランスフォーマの自動再適用でも、同じ順序が使用されます。  

初期クラスファイルバイトは、ClassLoader.defineClass または redefineClasses (変換の適用前) に渡されるバイトを表します。ただし、正確に一致しないことがあります。定数プールは同じレイアウトまたは内容であるとは限りません。定数プールのエントリ数が異なる可能性があります。定数プールのエントリの順序が異なることがあります。ただし、メソッドのバイトコードで定数プールのインデックスは対応します。一部の属性は存在しない可能性があります。順序が重要でない場合 (メソッドの順序など)、順序が維持されない場合があります。

このメソッドは、同時に 1 つ以上のクラスに対して相互依存の関係にある変更 (クラス A の再変換はクラス B の再変換を必要とするなど) を可能にするためにセット上で動作します。

再変換されたメソッドがアクティブなスタックフレームを持つ場合、アクティブなスタックフレームは元のメソッドのバイトコードを引き続き実行します。再変換されたメソッドは新しい呼び出しで使用されます。

このメソッドは、慣行の JVM セマンティクスの下で発生する初期化を除き、初期化を発生させません。つまり、クラスの再定義では、クラスの初期化子は実行されません。static 変数の値は呼び出し前の値のままに維持されます。

再変換されたクラスのインスタンスは影響を受けません。

再変換では、メソッドの本文、定数プール、および属性の変更が可能です。ただし、再変換では、フィールドまたはメソッドの追加、削除、あるいは名前の変更、メソッドのシグニチャーの変更、あるいは継承の変更はできません。これらの制約は、将来バージョンで解消される可能性があります。クラスバイトファイルがチェック、検証、およびインストールされるのは、変換の適用後になります。得られるバイトがエラーになると、このメソッドは例外をスローします。

このメソッドが例外をスローした場合、クラスの再変換は行われません。  

このメソッドは、class specification で記述されているように、インストゥルメンテーションで使用するものです。

パラメータ:
classes - 再変換するクラスの配列。長さゼロの配列は使用できるが、使用した場合、このメソッドは何も実行しない
例外:
UnmodifiableClassException - 指定されたクラスを変更できない場合 (isModifiableClass(java.lang.Class)false を返す)
UnsupportedOperationException - JVM の現在の設定が再変換 (isRetransformClassesSupported() が false) を許可しないか、再変換でサポートされない変更を加えようとした場合
ClassFormatError - データが有効なクラスを含まなかった場合
NoClassDefFoundError - クラスファイルの名前がクラスの名前と等しくない場合
UnsupportedClassVersionError - クラスファイルバージョン番号がサポートされていない場合
ClassCircularityError - 新しいクラスが循環を含む場合
LinkageError - リンケージエラーが発生した場合
NullPointerException - 提供されたクラス配列またはそのコンポーネントのいずれかが null の場合
導入されたバージョン:
1.6
関連項目:
isRetransformClassesSupported(), addTransformer(java.lang.instrument.ClassFileTransformer, boolean), ClassFileTransformer

isRedefineClassesSupported

boolean isRedefineClassesSupported()
現在の JVM 構成がクラスの再定義をサポートしているかどうかを返します。すでにロードされているクラスを再定義する機能は、JVM のオプションの機能です。再定義がサポートされるのは、エージェント JAR ファイルで Can-Redefine-Classes マニフェスト属性が true に設定されていて (package specification 参照)、かつ JVM がこの機能をサポートしている場合に限られます。単一の JVM の 1 つのインスタンス生成の間に、このメソッドに複数の呼び出しを行うと、常に同じ答えが返されます。

戻り値:
現在の JVM 構成がクラスの再定義をサポートする場合は true、サポートしない場合は false
関連項目:
redefineClasses(java.lang.instrument.ClassDefinition...)

redefineClasses

void redefineClasses(ClassDefinition... definitions)
                     throws ClassNotFoundException,
                            UnmodifiableClassException
提供されたクラスファイルを使って提供されたクラスのセットを再定義します。

このメソッドを使用して、既存のクラスファイルバイトへの参照のないクラスの定義を置き換えます。逐次デバッグを行うためにソースから再コンパイルするときに置き換えが行われます。既存のクラスファイルバイトが変換される場合は (バイトコードのインストゥルメンテーション内など)、retransformClasses を使用してください。

このメソッドは、同時に 1 つ以上のクラスに対して相互依存の関係にある変更 (クラス A の再定義はクラス B の再定義を必要とするなど) を可能にするためにセット上で動作します。

再定義されたメソッドがアクティブなスタックフレームを持つ場合、アクティブなスタックフレームは元のメソッドのバイトコードを引き続き実行します。再定義されたメソッドは新しい呼び出しで使用されます。

このメソッドは、慣行の JVM セマンティクスの下で発生する初期化を除き、初期化を発生させません。つまり、クラスの再定義では、クラスの初期化子は実行されません。static 変数の値は呼び出し前の値のままに維持されます。

再定義されたクラスのインスタンスは影響を受けません。

再定義では、メソッドの本文、定数プール、および属性の変更が可能です。ただし、再定義では、フィールドまたはメソッドの追加、削除、あるいは名前の変更、メソッドのシグニチャーの変更、あるいは継承の変更はできません。これらの制約は、将来バージョンで解消される可能性があります。クラスバイトファイルがチェック、検証、およびインストールされるのは、変換の適用後になります。得られるバイトがエラーになると、このメソッドは例外をスローします。

このメソッドが例外をスローした場合、クラスの再定義は行われません。  

このメソッドは、class specification で記述されているように、インストゥルメンテーションで使用するものです。

パラメータ:
definitions - 対応する定義を使って再定義するクラスの配列。長さゼロの配列は使用できるが、使用した場合、このメソッドは何も実行しない
例外:
UnmodifiableClassException - 指定されたクラスを変更できない場合 (isModifiableClass(java.lang.Class)false を返す)
UnsupportedOperationException - JVM の現在の設定が再定義 (isRedefineClassesSupported() が false) を許可しないか、再定義でサポートされない変更を加えようとした場合
ClassFormatError - データが有効なクラスを含まなかった場合
NoClassDefFoundError - クラスファイルの名前がクラスの名前と等しくない場合
UnsupportedClassVersionError - クラスファイルバージョン番号がサポートされていない場合
ClassCircularityError - 新しいクラスが循環を含む場合
LinkageError - リンケージエラーが発生した場合
NullPointerException - 提供された定義配列またはそのコンポーネントのいずれかが null の場合
ClassNotFoundException - スローすることはできない (互換性を維持するためにのみ存在する)
関連項目:
isRedefineClassesSupported(), addTransformer(java.lang.instrument.ClassFileTransformer, boolean), ClassFileTransformer

isModifiableClass

boolean isModifiableClass(Class<?> theClass)
クラスが 再変換 または 再定義 で変更可能かどうかを判定します。クラスが変更可能な場合、このメソッドは true を返します。クラスが変更不可能な場合、このメソッドは false を返します。  

再変換されるクラスでは、isRetransformClassesSupported() も true である必要があります。ただし、isRetransformClassesSupported() の値は、この関数が返す値に影響ありません。再定義されるクラスでは、isRedefineClassesSupported() も true である必要があります。ただし、isRedefineClassesSupported() の値は、この関数が返す値に影響ありません。  

java.lang.Integer.TYPE などのプリミティブクラスと配列クラスが変更可能になることはありません。

例外:
NullPointerException - 指定されたクラスが null である場合
導入されたバージョン:
1.6
関連項目:
retransformClasses(java.lang.Class...), isRetransformClassesSupported(), redefineClasses(java.lang.instrument.ClassDefinition...), isRedefineClassesSupported()

getAllLoadedClasses

Class[] getAllLoadedClasses()
JVM により現在ロードされているすべてのクラスの配列を返します。

戻り値:
JVM によりロードされたすべてのクラスを含む配列。クラスがない場合は長さゼロの配列

getInitiatedClasses

Class[] getInitiatedClasses(ClassLoader loader)
loader が起動ローダーであるすべてのクラスの配列を返します。提供されたローダーが null の場合、ブートストラップクラスローダーにより起動されたクラスが返されます。

パラメータ:
loader - 起動したクラスリストが返されるローダー
戻り値:
ローダーが起動ローダーであるすべてのクラスを含む配列。 クラスがない場合は長さゼロの配列

getObjectSize

long getObjectSize(Object objectToSize)
指定されたオブジェクトにより消費される記憶領域の容量の実装固有の近似値を返します。結果には、オブジェクトのオーバーヘッドの一部またはすべてが含まれる可能性があります。 したがって、実装内での比較には役立ちますが、実装間での比較には役立ちません。 JVM の単一の呼び出しの間に近似値が変わる可能性があります。

パラメータ:
objectToSize - サイズを評価するオブジェクト
戻り値:
指定されたオブジェクトにより消費される記憶領域の容量の実装固有の近似値
例外:
NullPointerException - 提供されたオブジェクトが null の場合

appendToBootstrapClassLoaderSearch

void appendToBootstrapClassLoaderSearch(JarFile jarfile)
ブートストラップクラスローダーで定義されるインストゥルメンテーションクラスで JAR ファイルを指定します。

「ブートストラップクラスローダー」と呼ばれる仮想マシンの組み込みクラスローダーがクラスの検索に失敗すると、JAR ファイル 内のエントリも検索されます。

このメソッドを複数回使用して、このメソッドが呼び出される順序で検索される複数の JAR ファイルを追加できます。

インストゥルメンテーションをするために、エージェントでは JAR ファイルにブートストラップクラスローダーで定義される以外のクラスまたはリソースが含まれないことを確認してください。この警告の監視に失敗すると、診断するのが困難な予期しない動作になることがあります。たとえばローダー L があり、委譲のための L の親がブートストラップクラスローダーであるとします。また、クラス C が L で定義され、クラス C のメソッドが public でないアクセス用クラス C$1 を参照するとします。JAR ファイルにクラス C$1 が含まれる場合、ブートストラップクラスローダーへの委譲により、C$1 がブートストラップクラスローダーによって定義されます。この例では IllegalAccessError がスローされ、アプリケーションが失敗します。このような問題を避ける 1 つの方法として、インストゥルメンテーションクラスに一意のパッケージ名を使用します。

Java 仮想マシン仕様』によると、Java 仮想マシンが以前にシンボリック参照を解決しようとして失敗した場合、その後このシンボリック参照を解決しようとしても必ず失敗し、最初に解決しようとした結果としてスローされたエラーと同じエラーになります。したがって、Java 仮想マシンが参照を解決できなかったクラスに対応するエントリが JAR ファイルに含まれる場合、その参照を解決しようとしても最初のエラーと同じエラーで失敗します。

パラメータ:
jarfile - ブートストラップクラスローダーがクラスの検索に失敗したときに検索される JAR ファイル
例外:
NullPointerException - jarfilenull の場合
導入されたバージョン:
1.6
関連項目:
appendToSystemClassLoaderSearch(java.util.jar.JarFile), ClassLoader, JarFile

appendToSystemClassLoaderSearch

void appendToSystemClassLoaderSearch(JarFile jarfile)
システムクラスローダーで定義されるインストゥルメンテーションクラスで JAR ファイルを指定します。 委譲用のシステムクラスローダー (getSystemClassLoader() を参照) がクラスの検索に失敗したときに、JarFile 内のエントリも検索されます。

このメソッドを複数回使用して、このメソッドが呼び出される順序で検索される複数の JAR ファイルを追加できます。

インストゥルメンテーションするために、エージェントは JAR ファイルにシステムクラスローダーで定義される以外のクラスまたはリソースが含まれないことを確認する必要があります。この警告の監視に失敗すると、診断するのが困難な予期しない動作になることがあります (appendToBootstrapClassLoaderSearch を参照)。

システムクラスローダーに appendToClassPathForInstrumentation メソッドが実装されている場合は、検索される JAR ファイルの追加がサポートされます。このメソッドは java.lang.String 型のパラメータ 1 つを取ります。public アクセスをするにはこのメソッドは必要ありません。JAR ファイルの名前は、jarfilegetName() メソッドを呼び出すことで取得され、jarfileappendtoClassPathForInstrumentation メソッドのパラメータとして提供されます。

Java 仮想マシン仕様』によると、Java 仮想マシンが以前にシンボリック参照を解決しようとして失敗した場合、その後このシンボリック参照を解決しようとしても必ず失敗し、最初に解決しようとした結果としてスローされたエラーと同じエラーになります。したがって、Java 仮想マシンが参照を解決できなかったクラスに対応するエントリが JAR ファイルに含まれる場合、その参照を解決しようとしても最初のエラーと同じエラーで失敗します。

このメソッドは java.class.path システムプロパティー の値を変更しません。

パラメータ:
jarfile - システムクラスローダーがクラスの検索に失敗したときに検索される JAR ファイル
例外:
UnsupportedOperationException - システムクラスローダーが検索される JAR ファイルの追加をサポートしていない場合
NullPointerException - jarfilenull の場合
導入されたバージョン:
1.6
関連項目:
appendToBootstrapClassLoaderSearch(java.util.jar.JarFile), ClassLoader.getSystemClassLoader(), JarFile

isNativeMethodPrefixSupported

boolean isNativeMethodPrefixSupported()
現在の JVM 設定で ネイティブメソッドの接頭辞の設定をサポートしているかどうかを返します。ネイティブメソッドの接頭辞を設定する機能は、JVM のオプション機能です。ネイティブメソッドの接頭辞の設定がサポートされるのは、エージェント JAR ファイルで Can-Set-Native-Method-Prefix マニフェスト属性が true に設定されていて (package specification 参照)、かつ JVM がこの機能をサポートしている場合に限られます。単一の JVM の 1 つのインスタンス生成の間に、このメソッドに複数の呼び出しを行うと、常に同じ答えが返されます。

戻り値:
現在の JVM 設定がネイティブメソッドの接頭辞の設定をサポートする場合は true、サポートしない場合は false
導入されたバージョン:
1.6
関連項目:
setNativeMethodPrefix(java.lang.instrument.ClassFileTransformer, java.lang.String)

setNativeMethodPrefix

void setNativeMethodPrefix(ClassFileTransformer transformer,
                           String prefix)
このメソッドは、名前に接頭辞を適用して再試行できるようにして、ネイティブメソッド解決のエラー処理を変更します。ClassFileTransformer に使用すると、ネイティブメソッドをインストゥルメンテーションできます。

ネイティブメソッドは直接インストゥルメンテーションできないため (バイトコードがないため)、インストゥルメンテーション可能なネイティブでないメソッドでラップする必要があります。たとえば次のメソッドを考えてみます。

native boolean foo(int x);

クラスの初期定義時に ClassFileTransformer を使用してクラスファイルを変換すると次のようになります。

boolean foo(int x) {
... record entry to foo ...
return wrapped_foo(x);
   }
   
native boolean wrapped_foo(int x);

ここで foo は実際のネイティブメソッドのラッパーで、接頭辞「wrapped_」が付けられています。「wrapped_」は、既存のメソッドの名前として使われていることが想像できるため、接頭辞の良い例ではありません。「$$$MyAgentWrapped$$$_」のようにすると良いですが、ここの例では見にくくなります。

ラッパーはネイティブメソッド呼び出しでデータを収集できますが、ラップされたメソッドとネイティブ実装とを結びつけることが問題になります。つまり、wrapped_foo メソッドは、たとえば次のような foo のネイティブ実装に解決される必要があります。

Java_somePackage_someClass_foo(JNIEnv* env, jint x)

この関数では接頭辞を指定でき、適切な解決が行われます。具体的には、標準の解決に失敗すると、接頭辞を考慮して解決が再試行されます。解決には 2 つの方法があります。JNI 関数 RegisterNatives を使用した明示的な解決と、通常の自動解決です。RegisterNatives を使用する場合、JVM では次の関連付けを行おうとします。

method(foo) -> nativeImplementation(foo)

これに失敗すると、指定された接頭辞をメソッド名の前に付けて解決が再試行され、次のような正しい解決が得られます。

method(wrapped_foo) -> nativeImplementation(foo)

自動解決では、JVM は次の関連付けを行おうとします。

method(wrapped_foo) -> nativeImplementation(wrapped_foo)

これに失敗すると、指定された接頭辞が実装名から削除されて解決が再試行され、次のような正しい解決が得られます。

method(wrapped_foo) -> nativeImplementation(foo)

接頭辞は標準の解決に失敗したときにのみ使用されるため、ネイティブメソッドを選択的にラップできます。

ClassFileTransformer では、独自のバイトコード変換を行うことができるため、複数レイヤーのラッパーを適用できます。そのため、各トランスフォーマには専用の接頭辞が必要です。変換は順番に適用されるため、接頭辞が適用される場合は、同じ順序で適用されます (addTransformer を参照)。つまり 3 つのトランスフォーマによってラッパーが適用されると、foo$trans3_$trans2_$trans1_foo のようになります。ただし、2 番目のトランスフォーマで foo にラッパーが適用されなかった場合は、$trans3_$trans1_foo のようになります。接頭辞のシーケンスを効率的に判断できるように、中間にくる接頭辞はネイティブでないラッパーが存在する場合のみ適用されます。つまりこの例では、$trans1_foo がネイティブメソッドでなくても、$trans1_foo が存在するため $trans1_ 接頭辞が適用されます。

パラメータ:
transformer - この接頭辞を使用してラップする ClassFileTransformer
prefix - ラップされたネイティブメソッドに適用された接頭辞
例外:
NullPointerException - null トランスフォーマを渡した場合
UnsupportedOperationException - JVM の現在の設定がネイティブメソッドの接頭辞 (isNativeMethodPrefixSupported() が false) の設定を許可しない場合
IllegalArgumentException - トランスフォーマが登録されていない場合 (addTransformer を参照)
導入されたバージョン:
1.6

JavaTM Platform
Standard Ed. 6

バグの報告と機能のリクエスト
さらに詳しい API リファレンスおよび開発者ドキュメントについては、Java SE 開発者用ドキュメントを参照してください。開発者向けの詳細な解説、概念の概要、用語の定義、バグの回避策、およびコード実例が含まれています。

Copyright 2006 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Documentation Redistribution Policy も参照してください。