|
JavaTM Platform Standard Ed. 6 |
|||||||||
前のクラス 次のクラス | フレームあり フレームなし | |||||||||
概要: 入れ子 | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド |
public interface Instrumentation
このクラスは、Java プログラミング言語コードを計測するためのサービスを提供します。インストゥルメンテーションとは、ツールで使用するデータを収集することを目的としてメソッドにバイトコードを追加することです。変更は単に追加されるため、これらのツールはアプリケーションの状態や動作を変更しません。状態や動作に影響を及ぼさないこの種のツールには、監視エージェント、プロファイラ、カバレージアナライザ、およびイベントロガーなどがあります。
Instrumentation
インタフェースのインスタンスを取得する方法は 2 つあります。
エージェントクラスを指定する方法で JVM を起動した場合。この場合、Instrumentation
インスタンスは、そのエージェントクラスの premain
メソッドに渡されます。
JVM の開始後にエージェントを開始する機構が JVM に用意されている場合。この場合、Instrumentation
インスタンスは、そのエージェントコードの agentmain
メソッドに渡されます。
これらの機構は、パッケージの仕様 で説明します。
エージェントが Instrumentation
インスタンスを取得すると、インスタンス上のメソッドをいつでも呼び出すことができます。
メソッドの概要 | |
---|---|
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)
このメソッドは、名前に接頭辞を適用して再試行できるようにして、ネイティブメソッド解決のエラー処理を変更します。 |
メソッドの詳細 |
---|
void addTransformer(ClassFileTransformer transformer, boolean canRetransform)
canRetransform
が true ならばクラスが 再変換 の場合に、クラスのロード時に呼び出されます。変換が呼び出される順序については、ClassFileTransformer.transform
を参照してください。トランスフォーマが実行中に例外をスローすると、JVM は登録されているその他のトランスフォーマを順に呼び出します。同じトランスフォーマを複数回追加することはできますが、そうするべきではありません。これを避けるには、トランスフォーマクラスの新しいインスタンスを作成してください。
このメソッドは、class specification で記述されているように、インストゥルメンテーションで使用するものです。
transformer
- 登録するトランスフォーマcanRetransform
- このトランスフォーマの変換を再変換できるかどうか
NullPointerException
- null
トランスフォーマを渡した場合
UnsupportedOperationException
- canRetransform
が true であり、JVM の現在の設定が再変換 (isRetransformClassesSupported()
が false) を許可しない場合void addTransformer(ClassFileTransformer transformer)
addTransformer(transformer, false)
と同じです。
transformer
- 登録するトランスフォーマ
NullPointerException
- null
トランスフォーマを渡した場合addTransformer(ClassFileTransformer,boolean)
boolean removeTransformer(ClassFileTransformer transformer)
transformer
- 登録を解除するトランスフォーマ
NullPointerException
- null
トランスフォーマを渡した場合boolean isRetransformClassesSupported()
Can-Retransform-Classes
マニフェスト属性が true
に設定されていて (package specification 参照)、かつ JVM がこの機能をサポートしている場合に限られます。単一の JVM の 1 つのインスタンス生成の間に、このメソッドに複数の呼び出しを行うと、常に同じ答えが返されます。
retransformClasses(java.lang.Class>...)
void retransformClasses(Class<?>... classes) throws UnmodifiableClassException
この機能は、すでにロード済みのクラスのインストゥルメンテーションを容易にします。クラスが最初にロードされたとき、またはクラスが 再定義 であるとき、初期クラスファイルバイトは ClassFileTransformer
で変換できます。この関数は、以前に変換が行われたかどうかには関係なく、変換処理を再実行します。この再変換は次の手順で行われます。
canRetransform
が false で追加されたトランスフォーマごとに、最後のクラスのロードまたは再定義中に 変換
で返されるバイトが変換の出力として再利用される。これは前回の変換をそのまま再適用することと同じである。ただし、変換
が呼び出されない点が異なる
canRetransform
が true で追加されたトランスフォーマごとに、トランスフォーマ内で 変換
メソッドが呼び出される
変換の順序については、変換
メソッドで説明しています。再変換不可能トランスフォーマの自動再適用でも、同じ順序が使用されます。
初期クラスファイルバイトは、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
の場合isRetransformClassesSupported()
,
addTransformer(java.lang.instrument.ClassFileTransformer, boolean)
,
ClassFileTransformer
boolean isRedefineClassesSupported()
Can-Redefine-Classes
マニフェスト属性が true
に設定されていて (package specification 参照)、かつ JVM がこの機能をサポートしている場合に限られます。単一の JVM の 1 つのインスタンス生成の間に、このメソッドに複数の呼び出しを行うと、常に同じ答えが返されます。
redefineClasses(java.lang.instrument.ClassDefinition...)
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
boolean isModifiableClass(Class<?> theClass)
true
を返します。クラスが変更不可能な場合、このメソッドは false
を返します。
再変換されるクラスでは、isRetransformClassesSupported()
も true である必要があります。ただし、isRetransformClassesSupported()
の値は、この関数が返す値に影響ありません。再定義されるクラスでは、isRedefineClassesSupported()
も true である必要があります。ただし、isRedefineClassesSupported()
の値は、この関数が返す値に影響ありません。
プリミティブクラス (java.lang.Integer.TYPE
など) と配列クラスが変更可能になることはありません。
NullPointerException
- 指定されたクラスが null
である場合retransformClasses(java.lang.Class>...)
,
isRetransformClassesSupported()
,
redefineClasses(java.lang.instrument.ClassDefinition...)
,
isRedefineClassesSupported()
Class[] getAllLoadedClasses()
Class[] getInitiatedClasses(ClassLoader loader)
loader
が起動ローダーであるすべてのクラスの配列を返します。提供されたローダーが null
の場合、ブートストラップクラスローダーにより起動されたクラスが返されます。
loader
- 起動したクラスリストが返されるローダー
long getObjectSize(Object objectToSize)
objectToSize
- サイズを評価するオブジェクト
NullPointerException
- 提供されたオブジェクトが null
の場合void appendToBootstrapClassLoaderSearch(JarFile jarfile)
「ブートストラップクラスローダー」と呼ばれる仮想マシンの組み込みクラスローダーがクラスの検索に失敗すると、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
- jarfile
が null
の場合appendToSystemClassLoaderSearch(java.util.jar.JarFile)
,
ClassLoader
,
JarFile
void appendToSystemClassLoaderSearch(JarFile jarfile)
getSystemClassLoader()
を参照) がクラスの検索に失敗したときに、JarFile
内のエントリも検索されます。
このメソッドを複数回使用して、このメソッドが呼び出される順序で検索される複数の JAR ファイルを追加できます。
インストゥルメンテーションするために、エージェントは JAR ファイルにシステムクラスローダーで定義される以外のクラスまたはリソースが含まれないことを確認する必要があります。この警告の監視に失敗すると、診断するのが困難な予期しない動作になることがあります (appendToBootstrapClassLoaderSearch
を参照)。
システムクラスローダーに appendToClassPathForInstrumentation
メソッドが実装されている場合は、検索される JAR ファイルの追加がサポートされます。このメソッドは java.lang.String
型のパラメータ 1 つを取ります。このメソッドは、public
アクセスを備えていなくてもかまいません。JAR ファイルの名前は、jarfile
の getName()
メソッドを呼び出すことで取得され、jarfile
は appendtoClassPathForInstrumentation
メソッドのパラメータとして提供されます。
『Java 仮想マシン仕様』によると、Java 仮想マシンが以前にシンボリック参照を解決しようとして失敗した場合、その後このシンボリック参照を解決しようとしても必ず失敗し、最初に解決しようとした結果としてスローされたエラーと同じエラーになります。したがって、Java 仮想マシンが参照を解決できなかったクラスに対応するエントリが JAR ファイルに含まれる場合、その参照を解決しようとしても最初のエラーと同じエラーで失敗します。
このメソッドは java.class.path
システムプロパティー
の値を変更しません。
jarfile
- システムクラスローダーがクラスの検索に失敗したときに検索される JAR ファイル
UnsupportedOperationException
- システムクラスローダーが検索される JAR ファイルの追加をサポートしていない場合
NullPointerException
- jarfile
が null
の場合appendToBootstrapClassLoaderSearch(java.util.jar.JarFile)
,
ClassLoader.getSystemClassLoader()
,
JarFile
boolean isNativeMethodPrefixSupported()
Can-Set-Native-Method-Prefix
マニフェスト属性が true
に設定されていて (package specification 参照)、かつ JVM がこの機能をサポートしている場合に限られます。単一の JVM の 1 つのインスタンス生成の間に、このメソッドに複数の呼び出しを行うと、常に同じ答えが返されます。
setNativeMethodPrefix(java.lang.instrument.ClassFileTransformer, java.lang.String)
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
- この接頭辞を使用してラップする ClassFileTransformerprefix
- ラップされたネイティブメソッドに適用された接頭辞
NullPointerException
- null
トランスフォーマを渡した場合
UnsupportedOperationException
- JVM の現在の設定がネイティブメソッドの接頭辞 (isNativeMethodPrefixSupported()
が false) の設定を許可しない場合
IllegalArgumentException
- トランスフォーマが登録されていない場合 (addTransformer
を参照)
|
JavaTM Platform Standard Ed. 6 |
|||||||||
前のクラス 次のクラス | フレームあり フレームなし | |||||||||
概要: 入れ子 | フィールド | コンストラクタ | メソッド | 詳細: フィールド | コンストラクタ | メソッド |
Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Documentation Redistribution Policy も参照してください。