JavaTM Virtual Machine Tool Interface
Version 1.1
|
JVMTI とは
JavaTM Virtual Machine Tool Interface (JVM TI) は、開発ツールや監視ツールで使用されるプログラミングインタフェースです。JVMTI は、JavaTM 仮想マシン (VM) で動作するアプリケーションの状態検査と実行制御の両方の機能を提供し、
プロファイリングツール、デバッグツール、監視ツール、スレッド分析ツール、カバレッジ分析ツールなど、VM の状態その他にアクセスする必要がある各種ツールの VM インタフェースとして機能します。
JVMTI は、JavaTM 仮想マシンのすべての実装で使用できるとは限りません。
JVM TI は、双方向のインタフェースです。以下では、JVM TI のクライアントを「エージェント」と呼びます。エージェントは、イベントから、さまざまな状態の発生通知を受け取ることができます。JVM TI は、イベントに応答して、またはイベントからは独立して、多くの関数を使ってアプリケーションへの照会および制御を実行できます。
個々のエージェントは同一のプロセスで実行され、検査対象のアプリケーションを実行する仮想マシンと直接通信します。この通信には、ネイティブインタ フェース (JVM TI) が使用されます。ネイティブのインプロセスインタフェースにより、ツール側への侵入は最小限に抑えながら、最大限の制御が可能になります。通常、エージェ ントは比較的コンパクトです。エージェントは、ターゲットアプリケーションの通常の実行を妨げることなく、ツールの機能の大部分を実装する別のプロセスによって制御できます。
アーキテクチャー
ツールへの書き込みは、JVM TI を使って直接行われるか、Java プラットフォームツールアーキテクチャーの高度インタフェースを使って間接的に行われます。Java Platform Debugger Architecture には、JVM TI のほかに、より高いレベルのアウトプロセスデバッガインタフェースも含まれています。多くのツールには、JVM TI よりも高いレベルのインタフェースの方が適しています。Java Platform Debugger Architecture の詳細については、Java Platform Debugger Architecture の Web サイトを参照してください。
エージェントの作成
エージェントの作成には、各種規則と C/C++ の定義を呼び出す C 言語をサポートする任意のネイティブ言語を使用できます。
JVM TI を使用するために必要な関数、イベント、データ型、定数の定義は、インクルードファイル jvmti.h で定義されます。これらの定義を使用するには、J2SETM インクルードディレクトリをインクルードパスに追加し、
#include <jvmti.h>
をソースコードに追加してください。
エージェントの配備
エージェントはプラットフォーム固有の方法で配備されますが、通常はそのプラットフォームでダイナミックライブラリに相当するものになります。たとえば、WindowsTM オペレーティングシステムの場合、エージェントライブラリは「ダイナミックリンクライブラリ」(DLL) になります。SolarisTM オペレーティング環境の場合、エージェントライブラリは共有オブジェクト (.so ファイル) になります。
VM 起動時にエージェントを起動するには、コマンド行オプションを使ってエージェントライブラリの名前を指定します。実装によっては、ライブ段階でエージェントを起動する機構をサポートしている可能性があります。その起動方法の詳細は、実装に固有となります。
JVMTI エージェントのコマンド行オプション
以下の「コマンド行オプション」という語は、JNI 呼び出し API の JNI_CreateJavaVM 関数において、JavaVMInitArgs 引数で指定されるオプションを意味します。
エージェントを適切にロードして実行するには、VM の起動時に次のいずれかのコマンド行オプションが必要です。これらの引数は、エージェントを含むライブラリと、起動時に渡されるオプションの文字列を指定します。
-
-agentlib:<agent-lib-name>=<options>
-
-agentlib: の後ろには、ロードするライブラリの名前を指定します。ライブラリのフルネームと場所の検索方法は、プラットフォームによって異なります。通常、<agent-lib-name> は、オペレーティングシステム固有のファイル名に展開されます。 は、起動時にエージェントに渡されます。たとえば、オプション -agentlib:foo=opt1,opt2 が指定された場合、VM は、WindowsTM ではシステムパス PATH から共有ライブラリ foo.dll をロードしようとします。SolarisTM オペレーティング環境では、LD_LIBRARY_PATH から libfoo.so をロードしようとします。
-
-agentpath:<path-to-agent>=<options>
-
-agentpath: の後ろには、ライブラリをロードする絶対パスを指定します。ライブラリ名の展開は行われません。 は、起動時にエージェントに渡されます。たとえば、オプション -agentpath:c:\myLibs\foo.dll=opt1,opt2 が指定された場合、VM は、共有ライブラリ c:\myLibs\foo.dll をロードしようとします。
ライブラリ内の起動ルーチン Agent_OnLoad が呼び出されます。
バイトコードインストゥルメンテーション (bytecode instrumentation) のために必要な場合、ツール内で Java プログラミング言語コードを使用しやすくするため、-agentlib: または -agentpath: を指定してロードされたライブラリから、JNI ネイティブメソッド実装が検索されます。
エージェントライブラリは、その他のすべてのライブラリが検索されたあと検索されます。非エージェントメソッドのネイティブメソッド実装を上書きまたは遮断するエージェントは、NativeMethodBind イベントを使用できます。
これらのスイッチは、上記の処理だけを行います。VM や JVM TI の状態を変更することはありません。JVM TI や JVM TI の一部を有効にする処理は、権限 (capability) により、プログラムを通して行われます。コマンド行オプションは必要ありません。
エージェントの起動
VM は、起動関数を呼び出すことで各エージェントを起動します。OnLoad 段階でエージェントを起動する場合は、関数 Agent_OnLoad が呼び出されます。ライブ段階でエージェントを起動する場合は、関数 Agent_OnAttach が呼び出されます。起動関数の呼び出しは、エージェントごとに 1 回だけ行われます。
エージェントの起動 (OnLoad 段階)
OnLoad 段階でエージェントを起動する場合、そのエージェントライブラリは次のプロトタイプを持つ起動関数をエクスポートする必要があります。
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
VM は、この関数を呼び出すことでエージェントを起動します。この呼び出しは VM 初期化の早い段階で行われるため、次のことが言えます。
-
システムプロパティーは、VM の起動で使用される前に設定できる
- すべての権限を使用できる (ただし、VM を構成する権限はこのときしか使用できない。 詳細は「権限関数」セクションを参照)
- バイトコードが実行されていない
- クラスがロードされていない
- オブジェクトが作成されていない
VM は、2 番目の引数として を指定して Agent_OnLoad 関数を呼び出します。つまり、コマンド行オプションの例を使用して、"opt1,opt2" は Agent_OnLoad の char *options 引数に渡されます。options 引数は、修正 UTF-8 文字列としてエンコードされます。= が指定されていない場合、options には長さ 0 の文字列が渡されます。options 文字列は、Agent_OnLoad 呼び出しの間有効です。必要な場合は、この期間が過ぎても、文字列または文字列の一部をコピーする必要があります。Agent_OnLoad が呼び出されてから終了するまでの期間を「ロード段階」と呼びます。VM はロード段階では初期化されません。このため、Agent_OnLoad 内部で許可された操作は限定されています (この時点で使用可能な機能については関数の説明を参照)。エージェントが安全に実行できるのは、オプションの処理や、SetEventCallbacks を使ってイベントコールバックを設定する処理です。VM 初期化イベントを受け取ってから (つまり、VMInit コールバックが呼び出されてから)、エージェントは初期化を完了できます。
原理の説明:
早い段階での起動が必要なのは、エージェントが必要な権限を設定できるようにするためです。多くの権限は、VM の初期化前に設定する必要があります。JVMDI では、-Xdebug コマンド行オプションで権限を制御できました。ただし、この制御は非常におおまかなものです。JVMPI 実装は、さまざまなテクニックを使って単一の「JVMPI オン」スイッチを提供します。必要な権限とパフォーマンスへの影響のバランスをとるために必要な細かい制御を提供するのに適したコマンド行オプションはありません。早い段階での起動には、エージェントが各種機能をインストールするため、ファイルシステムやシステムプロパティーに変更を加え、実行環境を制御できるようにする目的もあります。
Agent_OnLoad の戻り値は、エラーを示すために使用されます。ゼロ以外の値はエラーを表します。エラーが発生すると、VM は終了します。
エージェントの起動 (ライブ段階)
VM によっては、その VM 内でライブ段階でエージェントを起動する機構をサポートしている可能性があります。そのサポート方法の詳細は、実装に固有となります。たとえば、あるツールでは、なんらかのプラットフォーム固有の機構や実装固有の API を使用することで、実行中の VM に接続して特定のエージェントの起動を要求する可能性があります。
ライブ段階でエージェントを起動する場合、そのエージェントライブラリは次のプロトタイプを持つ起動関数をエクスポートする必要があります。
JNIEXPORT jint JNICALL
Agent_OnAttach(JavaVM* vm, char *options, void *reserved)
VM は、この関数を呼び出すことでエージェントを起動します。この呼び出しは、VM に接続されたスレッドのコンテキスト内で行われます。第 1 引数の は、Java VM です。 引数は、エージェントに指定された起動オプションです。 は、修正 UTF-8 文字列としてエンコードされます。起動オプションが指定されなかった場合、options には長さ 0 の文字列が渡されます。options 文字列は、Agent_OnAttach 呼び出しの間有効です。必要な場合は、この期間が過ぎても、文字列または文字列の一部をコピーする必要があります。
ライブ段階では権限の一部が使用できない可能性があります。
Agent_OnAttach 関数は、エージェントを初期化し、エラーが発生したかどうかを示す値を VM に返します。ゼロ以外の値はすべて、エラーを表します。エラーが発生しても VM は終了しません。代わりに VM は、そのエラーを無視するか、そのエラーを標準エラーに出力したりシステムログに記録したりするなど、なんらかの実装固有のアクションを実行します。
エージェントの停止
ライブラリは、オプションで、次のプロトタイプを持つ停止関数をエクスポートできます。
JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm)
この関数は、ライブラリのアンロードの直前に VM によって呼び出されます。プラットフォーム固有の機構に問題がある場合、アンロードが引き起こされ、この関数が呼び出されます (本書ではアンロード機構は指定しない)。正常な処理もしくは VM の障害 (起動時の障害を含む) によって VM が終了した場合、ライブラリは実際にアンロードされます。もちろん、制御できない停止は、この規則に当てはまりません。この関数と VM Death イベントには違いがあります。VM Death イベントを送信するためには、初期化の前に VM を実行したことがあり、VMDeath のコールバックを設定した有効な JVM TI 環境が存在し、イベントが有効になっている必要があります。これらの条件は、Agent_OnUnload には不要です。この関数は、ライブラリがその他の理由によってアンロードされたときも呼び出されます。VM Death イベントは、この関数が呼び出される前に送信されます (この関数が VM の終了によって呼び出される場合)。この関数を使って、エージェントによって割り当てられたリソースをクリーンアップすることができます。
埋め込み VM や単にスクリプト内の深い場所で起動される VM などでは、コマンド行のアクセスや変更が常に可能であるとは限らないため、JAVA_TOOL_OPTIONS 変数が用意されています。これを使えば、そうした場合でもエージェントを起動できます。
環境変数やその他の名前付き文字列をサポートするプラットホームでは、JAVA_TOOL_OPTIONS 変数に対応している場合があります。この変数は、オプションを空白文字で区切った文字列です。空白文字には、スペース、タブ、復帰 (CR)、復帰改行 (NL)、垂直タブ、用紙送り (FF) などがあります。連続する空白文字は空白文字 1 文字と同じであるとみなされます。オプションに空白文字を含める場合は、引用符で次のように囲んでください。
- 一重引用符の組 ('') に囲まれた、一重引用符を除くすべての文字は引用として囲まれる。
- 一重引用符の組の内部にある二重引用符には、特殊な意味はない。
- 二重引用符の組 ('') に囲まれた、二重引用符を除くすべての文字は引用として囲まれる。
- 二重引用符の組の内部にある一重引用符には、特殊な意味はない。
- 変数内の任意の場所を引用符で囲むことができる。
- 引用符で囲まれた空白文字には、特殊な意味はない。その他の文字と同様にオプションに含めることができ、区切り文字として機能しない。
- 引用符の組自体はオプションに含まれない。
JNI_CreateJavaVM (JNI 呼び出し API 内) は、これらのオプションをその JavaVMInitArgs 引数で指定されたオプションの先頭に付加します。プラットホームによっては、セキュリティー上の理由でこの機能を無効にしています。たとえばリファレンス実 装では、有効なユーザーまたはグループの ID が実際の ID と異なる場合に、Unix システム上でこの機能が無効になります。 この機能はツールの初期化、特にネイティブまたは Java プログラミング言語エージェントの起動をサポートするためのものです。複数のツールでこの機能を使用する可能性があります。そのため、変数は上書きせず、オプションを変数に追加するようにしてください。変数が処理されるのは JNI 呼び出し API の VM 作成呼び出し時であるため、起動側が処理するオプション (VM 選択オプションなど) は扱われません。
JVMTI 環境
JVM TI 仕様は、同時に複数の JVM TI エージェントを使用することを許可します。各エージェントには固有の JVM TI 環境が割り当てられます。つまり、JVM TI の状態はエージェントごとに異なっています。ある環境に変更を加えても、その他の環境に影響はありません。JVM TI 環境には、次の状態があります。
JVM TI の状態は独立していますが、エージェントは VM の共有の状態を検査し、変更します。また、エージェントが実行されるネイティブ環境を共有します。このため、あるエージェントがその他のエージェントの実行結果に影響を及ぼしたり、その他のエージェントの失敗の原因になることがあります。エージェントの作成者には、このエージェントとその他のエージェントとの互換性のレベルを指定する責任があります。JVM TI 実装は、エージェント間の悪影響を防ぐことはできません。これらの問題の発生を防ぐ技術については、本書では説明しません。
エージェントは、JNI 呼び出し API 関数 GetEnv にインタフェース ID として JVM TI のバージョン情報を渡すことによって、JVM TI 環境を作成します。JVM TI 環境の作成と使用の詳細については、「JVM TI 関数のアクセス」を参照してください。通常、JVM TI 環境は、Agent_OnLoad から GetEnv を呼び出すことによって作成されます。
バイトコードインストゥルメンテーション
このインタフェースは、プロファイリングをサポートするインタフェースで発生するイベントの一部を含みません。該当するイベントとして、オブジェクト割り 当てイベントやフルスピードメソッド入力/出力イベントがあります。このインタフェースは、ターゲットプログラムを構成する Java 仮想マシンのバイトコード命令を変更する「バイトコードインストゥルメンテーション (bytecode instrumentation)」機能をサポートします。通常、これらの変更では、メソッドのコードに「イベント」が追加されます。たとえば、メソッドの先頭に、MyProfiler.methodEntered() の呼び出しが追加されます。変更は純粋に追加であるため、アプリケーションの状態や動作を変更する必要はありません。挿入されるエージェントコードは標準バイトコードなので、VM をフルスピードで実行できます。このため、ターゲットプログラムだけでなく、インストゥルメンテーションも最適化されます。インストゥルメンテーションにバイトコードの実行からの切り替えが含まれない場合、効率の悪い状態の切り替えは不要です。結果として、イベントのパフォーマンスは高くなります。この方 法では、エージェントを完全に制御できます。インストゥルメンテーションは、コードの「重要な」部分 (エンドユーザーのコードなど) に限定可能で、条件付きにすることができます。インストゥルメンテーションは、完全に Java プログラミング言語コード内で実行できます。または、ネイティブエージェント内で呼び出すこともできます。インストゥルメンテーションは、カウンタを保持するだけの設定にしても、イベントの統計サンプルをとる設定にしてもかまいません。
インストゥルメンテーションの挿入は、次の 3 とおりのうちのいずれかの方法で行います。
-
静的インストゥルメンテーション: クラスファイルは VM にロードする前に計測されます。このために、たとえば、インストゥルメンテーションを追加するために変更された
*.class ファイルの重複ディレクトリを作成できます。この方法は非常に面倒です。一般に、エージェントはロードされるクラスファイルの出所を認識しません。
-
ロード時のインストゥルメンテーション: クラスファイルが VM にロードされるとき、クラスファイルの raw バイトは、インストゥルメンテーション用としてエージェントに送信されます。クラスのロードによって発生した
ClassFileLoadHook イベントが、この機能を提供します。この方法は効率がよく、1 回限りのインストゥルメンテーションに完全にアクセスできます。
-
動的インストゥルメンテーション: すでにロードされ、場合によっては実行されていることもあるクラスを変更します。このオプション機能は、
RetransformClasses 関数の呼び出しによって発生した ClassFileLoadHook イベントによって提供されます。クラスは何回でも変更できます。元の状態に戻すのも簡単です。この方法では、実行中のインストゥルメンテーションの変更が可能です。
このインタフェースに用意されたクラス変更機能は、インストゥルメンテーションの機構を提供し (ClassFileLoadHook イベントと RetransformClasses 関数)、開発時には修正しながらデバックを続けていく (RedefineClasses 関数) ために用意されています。
依存関係が混乱しないように、特にコアクラスを計測する場合は、注意が必要です。たとえば、各オブジェクト割り当ての通知を受けるアプローチでは、Object でコンストラクタを計測します。コンストラクタが最初は空であるとすると、このコンストラクタを次のように変更します。
public Object() {
MyProfiler.allocationTracker(this);
}
しかし、ClassFileLoadHook イベントを使用してこの変更を行った場合は、通常の VM に次のような影響があります。最初に作成されたオブジェクトがコンストラクタを呼び出して、MyProfiler のクラスがロードされます。 これによりオブジェクトが作成されますが、MyProfiler はまだロードされていないため、無限回帰が発生してしまい、スタックオーバーフローとなります。これを変更して、安全なタイミングになるまでトラッキングメソッドの呼び出しを遅らせます。たとえば trackAllocations を VMInit イベントのハンドラで設定することができます。
static boolean trackAllocations = false;
public Object() {
if (trackAllocations) {
MyProfiler.allocationTracker(this);
}
}
SetNativeMethodPrefix を使えば、ラッパーメソッドによるネイティブメソッドの計測が可能となります。
修正 UTF-8 の文字列エンコーディング
JVM TI は、修正 UTF-8 を使って文字列をエンコードします。これは、JNI が使用するのと同じエンコーディングです。修正 UTF-8 と標準の UTF-8 との違いは、補助文字と null 文字の表現方法にあります。詳細については、JNI 仕様の 「Modified UTF-8 Strings」セクションを参照してください。
仕様のコンテキスト
このインタフェースは Java 仮想マシンで実行されるアプリケーションの状態にアクセスするため、用語は JavaTM プラットホームに関するものであり、特に言及している場合を除いてネイティブプラットホームに関するものではありません。例を示します。
- 「スレッド」は JavaTM プログラミング言語のスレッドを意味する。
- 「スタックフレーム」は Java 仮想マシンのスタックフレームを意味する。
- 「クラス」は Java プログラミング言語のクラスを意味する。
- 「ヒープ」は Java 仮想マシンのヒープを意味する。
- 「モニター」は Java プログラミング言語のオブジェクトモニターを意味する。
Sun、Sun Microsystems、Sun のロゴ、Java、および JVM は、米国ならびにその他の国における米国 Sun Microsystems, Inc. の登録商標です。
関数
JVMTI 関数のアクセス
ネイティブコードは、JVM TI 関数を呼び出して JVM TI 機能にアクセスします。JVM TI 関数には、Java Native Interface (JNI) 関数のアクセス時と同様に、インタフェースポインタを使ってアクセスします。JVM TI インタフェースポインタを「環境ポインタ」と呼びます。
環境ポインタは、jvmtiEnv* 型の環境へのポインタです。環境には、JVM TI 接続に関する情報があります。環境内の最初の値は、関数テーブルへのポインタです。関数テーブルは、JVM TI 関数へのポインタの配列です。どの関数ポインタも配列内の事前に定義されたオフセットにあります。
C 言語から使用される場合: 関数へのアクセス時に二重間接指定が使用されます。つまり環境ポインタは、コンテキストを提供するとともに、各関数呼び出しの最初のパラメータになります。次に例を示します。
jvmtiEnv *jvmti;
...
jvmtiError err = (*jvmti)->GetLoadedClasses(jvmti, &class_count, &classes);
C++ 言語から使用される場合: 各関数は jvmtiEnv のメンバー関数としてアクセスされ、環境ポインタが関数呼び出しに渡されることはありません。次に例を示します。
jvmtiEnv *jvmti;
...
jvmtiError err = jvmti->GetLoadedClasses(&class_count, &classes);
特に指定しないかぎり、この仕様に含まれる例や宣言はすべて、C 言語を使用しています。
JVM TI 環境は、JNI 呼び出し API の GetEnv 関数を使って取得できます。
jvmtiEnv *jvmti;
...
(*jvm)->GetEnv(jvm, &jvmti, JVMTI_VERSION_1_0);
GetEnv を呼び出すたびに、新しい JVM TI 接続が作成され、新しい JVM TI 環境が作成されます。GetEnv は、JVM TI 版の version 引数を必要とします。返される環境のバージョンが要求されたバージョンと異なっていても、要求されたバージョンと互換性があれば、問題はありません。JVM TI がサポートされていないか、現在の VM 構成で JVM TI がサポートされていない場合、互換バージョンが得られないと、GetEnv は JNI_EVERSION を返します。特定のコンテキストでは、JVM TI 環境を作成するためにその他のインタフェースを追加できます。各環境には、固有の状態があります。たとえば、必須イベント、イベント処理関数、権限などです。環境は、DisposeEnvironment によってリリースされます。このため、スレッドごとに環境を持つ JNI とは異なり、JVM TI 環境は動的に作成され、複数のスレッドにまたがって機能します。
関数の戻り値
JVM TI 関数は、常に jvmtiError 関数の戻り値からエラーコードを返します。関数によっては、呼び出し側の関数で指定されたポインタにより、これ以外の値を返すことも可能です。JVM TI の関数の中にはメモリーを割り当てるものがありますが、この場合はプログラム内でそのメモリーを明示的に解放しなければなりません。これについては、個々の JVM TI 関数の説明に明記されています。空のリスト、配列、シーケンスなどは、NULL として返されます。
JVM TI 関数がエラーに遭遇した場合は (戻り値が JVMTI_ERROR_NONE 以外)、引数ポインタにより参照されるメモリー値は未定義です。しかし、メモリーおよびグローバル参照は何も割り当てられません。無効な入力によってエラーが 発生した場合、アクションは発生しません。
JNI オブジェクト参照の管理
JVM TI 関数は、JNI 参照 (jobject と jclass) とその派生 (jthread と jthreadGroup) によってオブジェクトを識別します。JVM TI の関数に渡される参照は、グローバルでもローカルでもかまいませんが、強い参照でなければなりません。JVM TI 関数から返されるすべての参照は、ローカル参照です。これらのローカル参照は、JVM TI の呼び出し時に作成されます。ローカル参照は、管理対象にするべきリソースです (JNI のマニュアルを参照)。スレッドがネイティブコードから返される場合、すべてのローカル参照は解放されます。典型的なエージェントスレッドを含む一部のスレッドは、決してネイティブコードからは返されません。各スレッドは、明示的管理なしで 16 個のローカル参照を作成することができます。ネイティブコードから返される前に、限定された数の JVM TI 呼び出しを実行するスレッド (イベント処理スレッドなど) の場合、明示的管理は不要であると判断されます。しかし、長時間実行されるエージェントスレッドは、明示的ローカル参照管理を必要とします。通常、この管理には、JNI 関数 PushLocalFrame と PopLocalFrame を使用します。逆に言えば、ネイティブコードから返されたあとも参照を保存する場合は、グローバル参照に変換する必要があります。これらの規則は jmethodID と jfieldID には適用されません。これらは jobject ではないからです。
関数呼び出しの必要条件
関数に、スレッドまたは VM を特定の状態 (中断など) にするのはエージェントであると明示的に指定されていないかぎり、関数を実行するために VM を一定の安全な状態にするのは、JVM TI 実装になります。
例外と関数
JVM TI 関数は例外をスローしません。エラー状態の伝達は、関数の戻り値を介して行われます。JVM TI 関数が呼び出されても、その前後で既存の例外状態はすべて保持されます。例外の処理方法については、JNI 仕様の 「Java Exceptions」セクションを参照してください。
関数の索引
メモリー管理
メモリー管理関数:
これらの関数は、JVM TI 機能が使用するメモリーの割り当て/割り当て解除を行うための機能を提供します。また、これらを使えば、エージェントの作業メモリーを提供できます。JVM TI が管理するメモリーとほかのメモリー割り当てライブラリおよび機構には、互換性がありません。
Allocate
jvmtiError
Allocate(jvmtiEnv* env,
jlong size,
unsigned char** mem_ptr)
JVM TI のアロケータを使用して、メモリーの領域を割り当てます。割り当てられたメモリーは、Deallocate によって解放してください。
|
名前
|
型
|
説明
|
size | jlong |
割り当てるバイト数。
原理の説明:
jlong は JVMDI との互換性を実現するために使用される。
|
mem_ptr | unsigned char** |
戻ったとき、割り当てられたメモリーの先頭を指すポインタ。size がゼロの場合、NULL が返される。
エージェントは unsigned char* にポインタを渡す。戻ったとき、unsigned char* は、サイズ size の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。 |
Deallocate
jvmtiError
Deallocate(jvmtiEnv* env,
unsigned char* mem)
JVM TI のアロケータを使用して、mem を解放します。この関数は、JVM TI の関数によって割り当てられて返されたメモリー (Allocate を使用して割り当てられたメモリーを含む) を解放するために使用します。割り当てられたすべてのメモリーを解除するまで、メモリーを再生することはできません。
|
名前
|
型
|
説明
|
mem | unsigned char
* |
割り当てられたメモリーの先頭を指すポインタ。[On return, the elements are set] は無視してよい。
エージェントは unsigned char に配列を渡す。配列の要素の値は無視される。戻ったとき、要素が設定されている。mem が NULL の場合、呼び出しが無視される。
|
スレッド
スレッド関数:
スレッドの関数型:
スレッドの型:
スレッドのフラグおよび定数:
スレッド状態の取得
jvmtiError
GetThreadState(jvmtiEnv* env,
jthread thread,
jint* thread_state_ptr)
スレッドの状態を取得します。スレッドの状態は、以下の一連の質問に答えることでわかります。
答えは次のビットベクトルで表されます。
|
定数
|
値
|
説明
|
JVMTI_THREAD_STATE_ALIVE | 0x0001 |
スレッドは活動状態。スレッドが新規 (起動していない) または終了した場合は、0。
|
JVMTI_THREAD_STATE_TERMINATED | 0x0002 |
スレッドは実行を完了した。
|
JVMTI_THREAD_STATE_RUNNABLE | 0x0004 |
スレッドは実行可能。
|
JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER | 0x0400 |
スレッドは同期ブロックまたはメソッドの入力を待機中。または Object.wait() のあとで、同期ブロックまたはメソッドの再入力を待機中。
|
JVMTI_THREAD_STATE_WAITING | 0x0080 |
スレッドは待機中。
|
JVMTI_THREAD_STATE_WAITING_INDEFINITELY | 0x0010 |
スレッドはタイムアウトなしで待機中。たとえば Object.wait()。
|
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT | 0x0020 |
スレッドは、指定された最大待機時間で待機中。たとえば Object.wait(long)。
|
JVMTI_THREAD_STATE_SLEEPING | 0x0040 |
スレッドはスリープ中 - Thread.sleep(long)。
|
JVMTI_THREAD_STATE_IN_OBJECT_WAIT | 0x0100 |
スレッドはオブジェクトモニターを待機中 - Object.wait。
|
JVMTI_THREAD_STATE_PARKED | 0x0200 |
スレッドは一時停止中。たとえば LockSupport.park、LockSupport.parkUtil、および LockSupport.parkNanos。
|
JVMTI_THREAD_STATE_SUSPENDED | 0x100000 |
スレッドが中断された。java.lang.Thread.suspend() または JVM TI の中断関数 (SuspendThread など) がスレッドで呼び出された。このビットが設定された場合、その他のビットは、スレッドの中断前の状態を参照する。
|
JVMTI_THREAD_STATE_INTERRUPTED | 0x200000 |
スレッド割り込みが発生した。
|
JVMTI_THREAD_STATE_IN_NATIVE | 0x400000 |
スレッドはネイティブコード内にある。つまり、VM または Java プログラミング言語コードに呼び戻されなかったネイティブメソッドが実行中。
このフラグは、VM でコンパイルされた Java プログラミング言語コードの実行中、VM コードの実行中、VM サポートコードの実行中は設定されないJNI および JVM TI 関数などのネイティブ VM インタフェース関数は、VM コードとして実装することも可能。
|
JVMTI_THREAD_STATE_VENDOR_1 | 0x10000000 |
VM ベンダーが定義する。
|
JVMTI_THREAD_STATE_VENDOR_2 | 0x20000000 |
VM ベンダーが定義する。
|
JVMTI_THREAD_STATE_VENDOR_3 | 0x40000000 |
VM ベンダーが定義する。
|
次の定義は、JVM TI スレッド状態を java.lang.Thread.State 形式の状態に変換するために使用します。
|
定数
|
値
|
説明
|
JVMTI_JAVA_LANG_THREAD_STATE_MASK | JVMTI_THREAD_STATE_TERMINATED | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
比較前に、この値で状態をマスクする
|
JVMTI_JAVA_LANG_THREAD_STATE_NEW | 0 |
java.lang.Thread.State.NEW
|
JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED | JVMTI_THREAD_STATE_TERMINATED |
java.lang.Thread.State.TERMINATED
|
JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE |
java.lang.Thread.State.RUNNABLE
|
JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER |
java.lang.Thread.State.BLOCKED
|
JVMTI_JAVA_LANG_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
java.lang.Thread.State.WAITING
|
JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
java.lang.Thread.State.TIMED_WAITING
|
規則
疑問に対する回答は 1 つ以上はありませんが、回答のないものもあります。それは回答がわからないか、あてはまらないか、回答のどれも正しくないためです。答は、括弧内の回答が 一致したときにだけ設定されます。つまり、次のいずれか 1 つ以上は設定できません。
-
JVMTI_THREAD_STATE_RUNNABLE
-
JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER
-
JVMTI_THREAD_STATE_WAITING
JVMTI_THREAD_STATE_ALIVE が設定されている場合、J2SETM 準拠実装では、以上のいずれかが常に設定されます。いずれかが設定されている場合は、括弧に囲まれた回答 JVMTI_THREAD_STATE_ALIVE が設定されます。以下のいずれか 1 つ以上は設定できません。
-
JVMTI_THREAD_STATE_WAITING_INDEFINITELY
-
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT
JVMTI_THREAD_STATE_WAITING が設定されている場合、J2SETM 準拠実装では、以上のいずれかが常に設定されます。いずれかが設定されている場合、括弧に囲まれた答 JVMTI_THREAD_STATE_ALIVE および JVMTI_THREAD_STATE_WAITING が設定されます。以下のいずれか 1 つ以上は設定できません。
-
JVMTI_THREAD_STATE_IN_OBJECT_WAIT
-
JVMTI_THREAD_STATE_PARKED
-
JVMTI_THREAD_STATE_SLEEPING
いずれかが設定されている場合、括弧に囲まれた回答 JVMTI_THREAD_STATE_ALIVE および JVMTI_THREAD_STATE_WAITING が設定されます。また JVMTI_THREAD_STATE_SLEEPING が設定されている場合は、JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT が設定されます。状態 A が状態 B の機構を使用して実装されている場合、この関数で返されるのは状態 A です。たとえば Thread.sleep(long) が Object.wait(long) を使用して実装されている場合は、返されるのは JVMTI_THREAD_STATE_SLEEPING のままです。以下は複数設定できます。
-
JVMTI_THREAD_STATE_SUSPENDED
-
JVMTI_THREAD_STATE_INTERRUPTED
-
JVMTI_THREAD_STATE_IN_NATIVE
ただし、いずれかが設定されると、JVMTI_THREAD_STATE_ALIVE が設定されます。
そして、JVMTI_THREAD_STATE_TERMINATED は JVMTI_THREAD_STATE_ALIVE が設定されるまでは設定されません。
スレッド状態の表現は、将来の仕様で拡張されることを考慮して設計されています。スレッド状態の値は、それに応じて使用されるべきであり、序数としては使 用しないでください。ほとんどの照会は、単一ビットをテストして行われています。 switch 文で使用する場合は、該当するビットで状態ビットをマスクしてください。上記で定義されていないすべてのビットは、将来使用するために予約されています。現在の仕様に互換の VM では、予約ビットを 0 に設定する必要があります。エージェントは予約ビットを無視しなければなりません。予約ビットは 0 であると想定しないでください。またそのため比較には含めないでください。
例
これから説明する値は、予約ビットとベンダービットを除外しています。
synchronized 文でブロックされたスレッドの状態は次のようになります。
JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER
開始していないスレッドの状態は次のようになります。
0
Object.wait(3000) によるスレッドの状態は次のようになります。
JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_WAITING +
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT +
JVMTI_THREAD_STATE_MONITOR_WAITING
実行可能中に中断されたスレッドの状態は次のようになります。
JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_RUNNABLE + JVMTI_THREAD_STATE_SUSPENDED
状態のテスト
ほとんどの場合、スレッドの状態は該当する状態に対応する 1 ビットをテストすれば判明します。たとえば、スレッドがスリープ状態かどうかをテストするコードは次のとおりです。
jint state;
jvmtiError err;
err = (*jvmti)->GetThreadState(jvmti, thread, &state);
if (err == JVMTI_ERROR_NONE) {
if (state & JVMTI_THREAD_STATE_SLEEPING) { ...
待機中 (Object.wait、一時停止中、またはスリープ中) の場合は、次のとおりです。
if (state & JVMTI_THREAD_STATE_WAITING) { ...
状態によっては、複数ビットをテストする必要があります。 スレッドが開始していないかどうかをテストする場合などです。
if ((state & (JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_TERMINATED)) == 0) { ...
時間指定した場合としていない場合の Object.wait を区別するには、次のようにします。
if (state & JVMTI_THREAD_STATE_IN_OBJECT_WAIT) {
if (state & JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT) {
printf("in Object.wait(long timeout)\n");
} else {
printf("in Object.wait()\n");
}
}
java.lang.Thread.State との関係
java.lang.Thread.getState() から返される java.lang.Thread.State で示されるスレッドの状態は、この関数から返される情報のサブセットです。対応する java.lang.Thread.State は、指定された変換マスクを使用して決定できます。たとえば、次のコードは java.lang.Thread.State スレッド状態の名前を返します。
err = (*jvmti)->GetThreadState(jvmti, thread, &state);
abortOnError(err);
switch (state & JVMTI_JAVA_LANG_THREAD_STATE_MASK) {
case JVMTI_JAVA_LANG_THREAD_STATE_NEW:
return "NEW";
case JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED:
return "TERMINATED";
case JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE:
return "RUNNABLE";
case JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED:
return "BLOCKED";
case JVMTI_JAVA_LANG_THREAD_STATE_WAITING:
return "WAITING";
case JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING:
return "TIMED_WAITING";
}
|
名前
|
型
|
説明
|
thread | jthread |
照会するスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
thread_state_ptr | jint* |
戻ったとき、スレッド状態フラグの定義に従って状 態フラグをポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
現在のスレッドの取得
jvmtiError
GetCurrentThread(jvmtiEnv* env,
jthread* thread_ptr)
現在のスレッドを取得します。現在のスレッドとは、この関数を呼び出した Java プログラミング言語スレッドのことです。
スレッドを引数に取る JVM TI 関数のほとんどは、NULL を現在のスレッドを意味するものとして受け入れます。
|
名前
|
型
|
説明
|
thread_ptr | jthread* |
戻ったとき、現在のスレッドをポイントする。
エージェントは jthread にポインタを渡す。戻ったとき、jthread が設定されている。thread_ptr から返されるオブジェクトは JNI ローカル参照であり、管理する必要がある。
|
すべてのスレッドの取得
jvmtiError
GetAllThreads(jvmtiEnv* env,
jint* threads_count_ptr,
jthread** threads_ptr)
すべてのライブスレッドを取得します。スレッドは、Java プログラミング言語のスレッド、つまり VM に接続されたスレッドです。スレッドがライブスレッドなら、java.lang.Thread.isAlive() の戻り値は true になります。 この場合、スレッドは、起動されたあと、まだ終了していません。スレッドの領域は、JVM TI 環境のコンテキストによって決定されます。通常、VM に接続されたすべてのスレッドが対象になります。これには JVM TI エージェントのスレッドも含まれます (RunAgentThread を参照)。
|
名前
|
型
|
説明
|
threads_count_ptr | jint* |
戻ったとき、スローされる例外の数をポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
threads_ptr | jthread** |
戻ったとき、参照 (実行中のスレッドごとに 1 つずつ) の配列をポイントする。
エージェントは jthread* にポインタを渡す。戻ったとき、jthread* は、サイズ *threads_count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。threads_ptr から返されるオブジェクトは JNI ローカル参照であり、管理する必要がある。
|
スレッドの中断
jvmtiError
SuspendThread(jvmtiEnv* env,
jthread thread)
指定されたスレッドを中断します。呼び出し側スレッドが指定されている場合、この関数は、ほかのスレッドが ResumeThread を呼び出すまで戻りません。スレッドが現在中断されている場合、この関数は何も行わず、エラーを返します。
|
名前
|
型
|
説明
|
thread | jthread |
中断するスレッド。
thread が NULL の場合、現在のスレッドが使用される
|
スレッドリストの中断
jvmtiError
SuspendThreadList(jvmtiEnv* env,
jint request_count,
const jthread* request_list,
jvmtiError* results)
request_list 配列に指定されたスレッド request_count を中断します。スレッドの再開には、ResumeThreadList または ResumeThread を使用します。request_list 配列に呼び出し側スレッドが指定されている場合、この関数は、ほかのスレッドによって再開されるまで戻りません。スレッドの中断中に発生したエラーは、こ の関数の戻り値ではなく、results 配列内に返されます。現在中断しているスレッドの状態は変わりません。
|
名前
|
型
|
説明
|
request_count | jint |
中断するスレッドの数。
|
request_list | const jthread* |
中断するスレッドのリスト。
エージェントは jthread の request_count 要素の配列を渡す。 |
results | jvmtiError* |
エージェントによって提供された request_count 要素の配列。戻ったとき、対応するスレッドの中断のエラーコードが入っている。スレッドがこの呼び出しによって中断した場合、エラーコードは JVMTI_ERROR_NONE。その他のエラーコードは、SuspendThread に指定されたエラーコード。
エージェントは、jvmtiError の request_count 要素を十分保持できる大きさの配列を渡す。配列の要素の値は無視される。戻ったとき、要素が設定されている。 |
スレッドの再開
jvmtiError
ResumeThread(jvmtiEnv* env,
jthread thread)
中断されているスレッドの実行を再開します。現在 JVM TI 中断関数 (SuspendThread など) または java.lang.Thread.suspend() によって中断されているスレッドの実行を再開します。その他のスレッドには影響はありません。
スレッドリストの再開
jvmtiError
ResumeThreadList(jvmtiEnv* env,
jint request_count,
const jthread* request_list,
jvmtiError* results)
request_list 配列に指定されたスレッド request_count を再開します。JVM TI 中断関数 (SuspendThreadList など) または java.lang.Thread.suspend() によって中断されているスレッドの実行を再開します。
|
名前
|
型
|
説明
|
request_count | jint |
再開するスレッドの数。
|
request_list | const jthread* |
再開するスレッド。
エージェントは jthread の request_count 要素の配列を渡す。 |
results | jvmtiError* |
エージェントによって提供された request_count 要素の配列。戻ったとき、対応するスレッドの再開のエラーコードが入っている。スレッドがこの呼び出しによって中断した場合、エラーコードは JVMTI_ERROR_NONE。その他のエラーコードは、ResumeThread に指定されたエラーコード。
エージェントは、jvmtiError の request_count 要素を十分保持できる大きさの配列を渡す。配列の要素の値は無視される。戻ったとき、要素が設定されている。 |
スレッドの停止
jvmtiError
StopThread(jvmtiEnv* env,
jthread thread,
jobject exception)
指定された非同期の例外を指定されたスレッドに送ります (java.lang.Thread.stop と同様)。通常、この関数は、指定されたスレッドを、例外 ThreadDeath のインスタンスを使って終了させるために使います。
スレッドの割り込み
jvmtiError
InterruptThread(jvmtiEnv* env,
jthread thread)
指定されたスレッドに割り込みます (java.lang.Thread.interrupt と同様)。
スレッド情報の取得
typedef struct {
char* name;
jint priority;
jboolean is_daemon;
jthreadGroup thread_group;
jobject context_class_loader;
} jvmtiThreadInfo;
jvmtiError
GetThreadInfo(jvmtiEnv* env,
jthread thread,
jvmtiThreadInfo* info_ptr)
スレッド情報を取得します。jvmtiThreadInfo 構造体のフィールドに、指定されたスレッドの詳細が入ります。
|
名前
|
型
|
説明
|
thread | jthread |
照会するスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
info_ptr | jvmtiThreadInfo* |
戻ったとき、指定されたスレッドについての情報が入っている。
コンテキストクラスローダーを認識しない JDK 1.1 の実装の場合、context_class_loader フィールドは NULL。
エージェントは jvmtiThreadInfo にポインタを渡す。戻ったとき、jvmtiThreadInfo が設定されている。jvmtiThreadInfo の name フィールドに返されるポインタは、新しく割り当てられた配列。この配列は、Deallocate を使って解放する必要がある。jvmtiThreadInfo の thread_group フィールドに返されるオブジェクトは、JNI ローカル参照であり、管理する必要がある。jvmtiThreadInfo の context_class_loader フィールドに返されるオブジェクトは、JNI ローカル参照であり、管理する必要がある。
|
所有モニター情報の取得
jvmtiError
GetOwnedMonitorInfo(jvmtiEnv* env,
jthread thread,
jint* owned_monitor_count_ptr,
jobject** owned_monitors_ptr)
指定されたスレッドが所有するモニターについての情報を取得します。
|
名前
|
型
|
説明
|
thread | jthread |
照会するスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
owned_monitor_count_ptr | jint* |
返されるモニターの数。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
owned_monitors_ptr | jobject** |
所有されるモニターの配列。
エージェントは jobject* にポインタを渡す。戻ったとき、jobject* は、サイズ *owned_monitor_count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。
owned_monitors_ptr から返されるオブジェクトは JNI ローカル参照であり、管理する必要がある。
|
所有モニターのスタックの深さ情報の取得
typedef struct {
jobject monitor;
jint stack_depth;
} jvmtiMonitorStackDepthInfo;
jvmtiError
GetOwnedMonitorStackDepthInfo(jvmtiEnv* env,
jthread thread,
jint* monitor_info_count_ptr,
jvmtiMonitorStackDepthInfo** monitor_info_ptr)
指定されたスレッドが所有するモニターに関する情報と、それらのモニターをロックしているスタックフレームの深さを取得します。
|
フィールド
|
型
|
説明
|
monitor | jobject |
所有されるモニター。
|
stack_depth | jint |
スタックの深さ。スタックフレーム関数で使用されるスタックの深さに対応している。つまり、0 は現在のフレームを、1 は現在のフレームを呼び出したフレームをそれぞれ表す。また、実装がスタックの深さを判断できない場合は - 1 になる (JNI の MonitorEnter を使って取得されたモニターの場合など)。
|
|
名前
|
型
|
説明
|
thread | jthread |
照会するスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
monitor_info_count_ptr | jint* |
返されるモニターの数。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
monitor_info_ptr | jvmtiMonitorStackDepthInfo ** |
所有されるモニターの深さ情報の配列。
エージェントは jvmtiMonitorStackDepthInfo* にポインタを渡す。戻ったとき、jvmtiMonitorStackDepthInfo* は、サイズ *owned_monitor_depth_count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。jvmtiThreadGroupInfo の monitor フィールドに返されるオブジェクトは、JNI ローカル参照であり、管理する必要がある。
|
現在競合しているモニターの取得
jvmtiError
GetCurrentContendedMonitor(jvmtiEnv* env,
jthread thread,
jobject* monitor_ptr)
指定されたスレッドが、java.lang.Object.wait を使ってオブジェクトのモニターに入るか、モニターを獲得し直すのを待機している場合に、そのオブジェクトを取得します。
|
名前
|
型
|
説明
|
thread | jthread |
照会するスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
monitor_ptr | jobject* |
戻ったとき、現在競合しているモニターが入っている。そのようなモニターがない場合は NULL が入っている。
エージェントは jobject にポインタを渡す。戻ったとき、jobject が設定されている。monitors_ptr から返されるオブジェクトは JNI ローカル参照であり、管理する必要がある。
|
エージェント起動関数
typedef void (JNICALL *jvmtiStartFunction)
(jvmtiEnv* jvmti_env,
JNIEnv* jni_env,
void* arg);
エージェントによって提供されるコールバック関数。この関数は、RunAgentThread で開始されるエージェントスレッドのエントリポイントになります。
|
エージェントスレッドの実行
jvmtiError
RunAgentThread(jvmtiEnv* env,
jthread thread,
jvmtiStartFunction proc,
const void* arg,
jint priority)
指定されたネイティブ関数を使って、エージェントスレッドの実行を開始します。パラメータ arg は起動関数 (proc で指定) の単一の引数として転送されます。この関数により、java.lang.Thread の特別なサブクラスや java.lang.Runnable の実装側をロードせずに、別のプロセスとの通信処理またはイベント処理用のエージェントスレッドを作成できます。その代わり、作成されたスレッドは完全にネイティブコード内で実行できます。ただし、作成するスレッドには、java.lang.Thread の新しく作成されたインスタンス (引数 thread によって参照される) が必要で、そのインスタンスにスレッドを関連付けます。スレッドオブジェクトは、JNI 呼び出しで作成できます。
次に一般的なスレッド優先順位を参考として示します。
|
定数
|
値
|
説明
|
JVMTI_THREAD_MIN_PRIORITY | 1 |
一番低い優先順位
|
JVMTI_THREAD_NORM_PRIORITY | 5 |
中間の優先順位
|
JVMTI_THREAD_MAX_PRIORITY | 10 |
一番高い優先順位
|
新しいスレッドは、指定の優先順位で、デーモンスレッドとして起動されます。有効な場合は、ThreadStart イベントが送信されます。
スレッドの起動が完了しているため、このスレッドはこの関数が戻る際にライブ状態になっています。ただし、このスレッドがすぐに終了した場合は除きます。
このスレッドのスレッドグループは無視されます。具体的には、このスレッドは、スレッドグループに追加されず、Java プログラミング言語、JVM TI のいずれのレベルでもスレッドグループのクエリーには表示されません。
このスレッドは、Java プログラミング言語のクエリーでは表示されませんが、GetAllThreads や GetAllStackTraces など、JVM TI のクエリーには含まれます。
proc の実行時に、新しいスレッドは VM に接続されます。JNI のマニュアルの「Attaching to the VM」を参照してください。
|
名前
|
型
|
説明
|
thread | jthread |
実行するスレッド。
|
proc | jvmtiStartFunction |
起動関数
|
arg | const void
* |
起動関数の引数。
エージェントがポインタを渡す。arg が NULL の場合、起動関数に NULL が渡される。
|
priority | jint |
開始されるスレッドの優先順位。java.lang.Thread.setPriority で許可されているスレッド優先順位を使用できる (jvmtiThreadPriority の優先順位を含む)。
|
スレッドローカルな記憶領域の設定
jvmtiError
SetThreadLocalStorage(jvmtiEnv* env,
jthread thread,
const void* data)
VM は、個々の環境スレッドペアに関連付けられたポインタ値を格納します。このポインタ値を「スレッドローカルな記憶領域」と呼びます。この関数で設定されない場合、値は NULL になります。エージェントは、スレッド固有の情報を格納するため、メモリーを割り当てることができます。スレッドローカルな記憶領域を設定することにより、GetThreadLocalStorage を使ってアクセスできるようになります。
この関数は、JVM TI のスレッドローカルな記憶領域の値を設定するため、エージェントによって呼び出されます。JVM TI は、エージェントに対して、スレッドごとの情報を記録するために利用できる、ポインタサイズのスレッドローカルな記憶領域を提供します。
|
名前
|
型
|
説明
|
thread | jthread |
このスレッドを格納する。
thread が NULL の場合、現在のスレッドが使用される。
|
data | const void
* |
スレッドローカルな記憶領域に入力する値。
エージェントがポインタを渡す。data が NULL の場合、値は NULL に設定される。
|
スレッドローカルな記憶領域の取得
jvmtiError
GetThreadLocalStorage(jvmtiEnv* env,
jthread thread,
void** data_ptr)
JVM TI のスレッドローカルな記憶領域の値を取得するため、エージェントによって呼び出されます。
|
名前
|
型
|
説明
|
thread | jthread |
このスレッドから取得する。
thread が NULL の場合、現在のスレッドが使用される。
|
data_ptr | void** |
スレッドローカルな記憶領域の値を返すポインタ。スレッドローカルな記憶領域が SetThreadLocalStorage で設定されていない場合、返されるポインタは NULL。
|
スレッドグループ
スレッドグループ関数:
スレッドグループの型:
トップレベルのスレッドグループの取得
jvmtiError
GetTopThreadGroups(jvmtiEnv* env,
jint* group_count_ptr,
jthreadGroup** groups_ptr)
VM 内のトップレベルの (親がない) スレッドグループをすべて返します。
|
名前
|
型
|
説明
|
group_count_ptr | jint* |
戻ったとき、トップレベルのスレッドグループの数をポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
groups_ptr | jthreadGroup** |
戻ったとき、トップレベルのスレッドグループの配列を指すポインタを参照する。
エージェントは jthreadGroup* にポインタを渡す。戻ったとき、jthreadGroup* は、サイズ *group_count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。groups_ptr から返されるオブジェクトは JNI ローカル参照であり、管理する必要がある。
|
スレッドグループ情報の取得
typedef struct {
jthreadGroup parent;
char* name;
jint max_priority;
jboolean is_daemon;
} jvmtiThreadGroupInfo;
jvmtiError
GetThreadGroupInfo(jvmtiEnv* env,
jthreadGroup group,
jvmtiThreadGroupInfo* info_ptr)
スレッドグループの情報を取得します。jvmtiThreadGroupInfo 構造体のフィールドに、指定されたスレッドグループの詳細が入ります。
|
フィールド
|
型
|
説明
|
parent | jthreadGroup |
親スレッドグループ。
|
name | char * |
スレッドグループの名前。修正 UTF-8 文字列としてエンコードされる。
|
max_priority | jint |
このスレッドグループの最高の優先順位。
|
is_daemon | jboolean |
デーモンスレッドグループかどうか。
|
|
名前
|
型
|
説明
|
group | jthreadGroup |
照会するスレッドグループ。
|
info_ptr | jvmtiThreadGroupInfo* |
戻ったとき、指定されたスレッドグループについての情報が入っている。
エージェントは jvmtiThreadGroupInfo にポインタを渡す。戻ったとき、jvmtiThreadGroupInfo が設定されている。jvmtiThreadGroupInfo の parent フィールドに返されるオブジェクトは、JNI ローカル参照であり、管理する必要がある。jvmtiThreadGroupInfo の name フィールドに返されるポインタは、新しく割り当てられた配列。この配列は、Deallocate を使って解放する必要がある。 |
子スレッドグループの取得
jvmtiError
GetThreadGroupChildren(jvmtiEnv* env,
jthreadGroup group,
jint* thread_count_ptr,
jthread** threads_ptr,
jint* group_count_ptr,
jthreadGroup** groups_ptr)
このスレッドグループ内のアクティブスレッドとアクティブサブグループを取得します。
|
名前
|
型
|
説明
|
group | jthreadGroup |
照会するグループ。
|
thread_count_ptr | jint* |
戻ったとき、このスレッドグループ内のアクティブスレッドの数をポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
threads_ptr | jthread** |
戻ったとき、このスレッドグループ内のアクティブスレッドの配列をポイントする。
エージェントは jthread* にポインタを渡す。戻ったとき、jthread* は、サイズ *thread_count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。threads_ptr から返されるオブジェクトは JNI ローカル参照であり、管理する必要がある。
|
group_count_ptr | jint* |
戻ったとき、アクティブな子スレッドグループの数をポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
groups_ptr | jthreadGroup** |
戻ったとき、アクティブな子スレッドグループの配列をポイントする。
エージェントは jthreadGroup* にポインタを渡す。戻ったとき、jthreadGroup* は、サイズ *group_count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。groups_ptr から返されるオブジェクトは JNI ローカル参照であり、管理する必要がある。
|
スタックフレーム
スタックフレーム関数:
スタックフレームの型:
これらの関数は、スレッドのスタックに関する情報を提供します。スタックフレームは、深さで参照されます。深さゼロのフレームが現在のフレームです。
スタックフレームについては、『Java 仮想マシン仕様』の「Frames」セクションに記載されています。つまり、これらのフレームは、ネイティブメソッドを含むメソッドの呼び出しに対応しているが、プラットフォーム固有のフレームや VM 内部のフレームには対応していません。
JVM TI 実装がメソッド呼び出しを使ってスレッドを起動し、これらの関数が提供するスタック内に、対応するフレームを含めることができます。つまり、main() や run() よりも深い位置に表示されるフレームが存在することになります。ただし、この提供は、スタックフレームまたはスタックの深さを使用するすべての JVM TI 機能と整合性がとれたものでなければいけません。
スタックフレーム情報構造体
スタックフレームに関する情報は次の構造体で戻されます。
typedef struct {
jmethodID method;
jlocation location;
} jvmtiFrameInfo;
|
フィールド
|
型
|
説明
|
method | jmethodID |
このフレーム内で実行されているメソッド。
|
location | jlocation |
このフレーム内で実行されている命令のインデックス。フレームがネイティブメソッドを実行している場合は -1。
|
スタック情報構造体
スタックフレームセットに関する情報は次の構造体で戻されます。
typedef struct {
jthread thread;
jint state;
jvmtiFrameInfo* frame_buffer;
jint frame_count;
} jvmtiStackInfo;
|
フィールド
|
型
|
説明
|
thread | jthread |
戻ったとき、トレースされたスレッド。
|
state | jint |
戻ったとき、スレッドの状態。「GetThreadState」を 参照。
|
frame_buffer | jvmtiFrameInfo * |
戻ったとき、このエージェントによって割り当てられたバッファーに、スタックフレーム情報が入っている。
|
frame_count | jint |
戻ったとき、レコード数が frame_buffer に入っている。これは min(max_frame_count, stackDepth) になる。
|
スタックトレースの取得
jvmtiError
GetStackTrace(jvmtiEnv* env,
jthread thread,
jint start_depth,
jint max_frame_count,
jvmtiFrameInfo* frame_buffer,
jint* count_ptr)
スレッドのスタックに関する情報を取得します。max_frame_count がスタックの深さより小さい場合、max_frame_count の一番上のフレームが返されます。それ以外の場合、スタック全体が返されます。最後に呼び出されたフレームである最上位フレームが、返されるバッファーの先頭になります。
次の例では、一番上のフレームから 5 つめまでのフレームが返されます。さらに、フレームがある場合は、現在実行しているメソッドの名前が出力されます。
jvmtiFrameInfo frames[5];
jint count;
jvmtiError err;
err = (*jvmti)->GetStackTrace(jvmti, aThread, 0, 5,
&frames, &count);
if (err == JVMTI_ERROR_NONE && count >= 1) {
char *methodName;
err = (*jvmti)->GetMethodName(jvmti, frames[0].method,
&methodName, NULL);
if (err == JVMTI_ERROR_NONE) {
printf("Executing method: %s", methodName);
}
}
thread は、中断することなく、この関数を呼び出すことができます。
位置と行番号のマッピングには、GetLineNumberTable 関数を使用できます。このマッピングは、遅延してもかまいません。
|
名前
|
型
|
説明
|
thread | jthread |
このスレッドのスタックトレースをフェッチする。
thread が NULL の場合、現在のスレッドが使用される。
|
start_depth | jint |
この深さでフレームの取得を開始する。負の数でない場合、現在のフレームからカウントする。深さが start_depth のフレームが最初に取得される。たとえば、0 の場合、現在のフレームから開始する。 1 の場合、現在のフレームの呼び出し側から開始する。 2 の場合、現在のフレームの呼び出し側の呼び出し側から開始する。負の数の場合、一番古いフレームの下からカウントする。 深さが stackDepth+ start_depth (stackDepth はスタック上のフレームのカウント) のフレームが最初に取得される。たとえば、-1 の場合、一番古いフレームだけが取得される。 -2 の場合、一番古いフレームによって呼び出されたフレームから開始する。
|
max_frame_count | jint |
取得する jvmtiFrameInfo レコードの最大数。
|
frame_buffer | jvmtiFrameInfo * |
戻ったとき、このエージェントによって割り当てられたバッファーに、スタックフレーム情報が入っている。
エージェントは、jvmtiFrameInfo の max_frame_count 要素を十分保持できる大きさの配列を渡す。配列の要素の値は無視される。戻ったとき、要素の *count_ptr が設定される。 |
count_ptr | jint* |
戻ったとき、情報を入力されるレコードの数をポイントする。 start_depth が負の数でない場合、min(max_frame_count, stackDepth - start_depth)。start_depth が負の数の場合、min(max_frame_count, -start_depth)。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
すべてのスタックトレースの取得
jvmtiError
GetAllStackTraces(jvmtiEnv* env,
jint max_frame_count,
jvmtiStackInfo** stack_info_ptr,
jint* thread_count_ptr)
すべてのライブスレッドのスタックに関する情報を取得します (エージェントスレッドを含む)。max_frame_count がスタックの深さより小さい場合、そのスレッドについて max_frame_count の一番上のフレームが返されます。それ以外の場合、スタック全体が返されます。最後に呼び出されたフレームである最上位フレームが、返されるバッファーの先頭になります。
すべてのスタックは、同時に収集されます。つまり、あるスレッドのサンプリングと次のスレッドのサンプリングとの間には、スレッドの状態またはスタックに変更は発生しません。スレッドを中断する必要はありません。
jvmtiStackInfo *stack_info;
jint thread_count;
int ti;
jvmtiError err;
err = (*jvmti)->GetAllStackTraces(jvmti, MAX_FRAMES, &stack_info, &thread_count);
if (err != JVMTI_ERROR_NONE) {
...
}
for (ti = 0; ti < thread_count; ++ti) {
jvmtiStackInfo *infop = &stack_info[ti];
jthread thread = infop->thread;
jint state = infop->state;
jvmtiFrameInfo *frames = infop->frame_buffer;
int fi;
myThreadAndStatePrinter(thread, state);
for (fi = 0; fi < infop->frame_count; fi++) {
myFramePrinter(frames[fi].method, frames[fi].location);
}
}
/* this one Deallocate call frees all data allocated by GetAllStackTraces */
err = (*jvmti)->Deallocate(jvmti, stack_info);
スレッドリストのスタックトレースの取得
jvmtiError
GetThreadListStackTraces(jvmtiEnv* env,
jint thread_count,
const jthread* thread_list,
jint max_frame_count,
jvmtiStackInfo** stack_info_ptr)
指定されたスレッドのスタックに関する情報を取得します。max_frame_count がスタックの深さより小さい場合、そのスレッドについて max_frame_count の一番上のフレームが返されます。それ以外の場合、スタック全体が返されます。最後に呼び出されたフレームである最上位フレームが、返されるバッファーの先頭になります。
すべてのスタックは、同時に収集されます。つまり、あるスレッドのサンプリングと次のスレッドのサンプリングとの間には、スレッドの状態またはスタックに 変更は発生しません。スレッドを中断する必要はありません。
スレッドがまだ起動されていないか、スタック情報が収集される前にスレッドが終了した場合は、長さ 0 のスタック (jvmtiStackInfo.frame_count が 0) が返されるため、スレッド jvmtiStackInfo.state をチェックできます。
例は、同様な関数 GetAllStackTraces を参照してください。
フレームカウントの取得
jvmtiError
GetFrameCount(jvmtiEnv* env,
jthread thread,
jint* count_ptr)
指定されたスレッドの呼び出しスタックに現在入っているフレームの数を取得します。
アクティブにバイトコードを実行しているスレッド (現在のスレッドではなく、中断されていないスレッドなど) のためにこの関数が呼び出された場合、一時的な情報が返されます。
|
名前
|
型
|
説明
|
thread | jthread |
照会するスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
count_ptr | jint* |
戻ったとき、呼び出しスタック内のフレームの数をポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
フレームのポップ
jvmtiError
PopFrame(jvmtiEnv* env,
jthread thread)
thread スタックの現在のフレームをポップします。フレームをポップすると、直前のフレームに戻ります。スレッドが再開されると、スレッドの実行状態は、メソッドが呼び出される直前の状態にリセットされます。『Java 仮想マシン仕様』の用語で説明すると、次のようになります。
- 現在のフレームが破棄され、以前のフレームが現在のフレームになる
- オペランドスタックが回復する。引数の値が再度追加され、呼び出しが
invokestatic でない場合は objectref も再度追加される
- Java 仮想マシンの PC が呼び出し命令の操作コード (opcode) へ回復する
ただし、呼び出し先のメソッドで発生した引数の変更内容は保持されます。実行を続行すると、最初の実行指示が呼び出しとなります。
PopFrame の呼び出しとスレッドの再開の間、スタックの状態は未定義です。最初のフレームよりも前にフレームをポップするには、次の 3 つの手順を繰り返す必要があります。
- イベントを通じてスレッドを中断する (ステップ、ブレークポイントなど)
PopFrame を呼び出す
- スレッドを再開する
被呼び出しメソッドを呼び出すことによって獲得されたロック (これが synchronized メソッドの場合) と、被呼び出しメソッド内の synchronized ブロックに入ることによって獲得されたロックは解放されます。注:これは、ネイティブロックや java.util.concurrent.locks ロックには適用されません。
最終的に、ブロックは実行されません。
グローバル状態への変更には対応しないので、変更は行われません。
指定されたスレッドは中断されていなければいけません。これは、そのスレッドが現在のスレッドであってはいけないことを意味します。
被呼び出しメソッドと呼び出し側のメソッドのどちらも、非ネイティブの Java プログラミング言語のメソッドとします。
この関数は、JVM TI イベントを生成しません。
|
名前
|
型
|
説明
|
thread | jthread |
ポップする現在のフレームのスレッド。
|
フレームの位置の取得
jvmtiError
GetFrameLocation(jvmtiEnv* env,
jthread thread,
jint depth,
jmethodID* method_ptr,
jlocation* location_ptr)
Java プログラミング言語のフレームについて、現在実行中の命令の位置を返します。
|
名前
|
型
|
説明
|
thread | jthread |
照会するフレームのスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
depth | jint |
照会するフレームの深さ。
|
method_ptr | jmethodID* |
戻ったとき、現在の位置のメソッドをポイントする。
エージェントは jmethodID にポインタを渡す。戻ったとき、jmethodID が設定されている。 |
location_ptr | jlocation* |
戻ったとき、現在実行中の命令のインデックスをポイントする。フレームがネイティブメソッドを実行している場合は -1 に設定される。
エージェントは jlocation にポインタを渡す。戻ったとき、jlocation が設定されている。 |
フレームのポップの通知
jvmtiError
NotifyFramePop(jvmtiEnv* env,
jthread thread,
jint depth)
深さ depth のフレームがスタックからポップされたとき、FramePop イベントを生成します。詳細は、FramePop イベントの説明を参照してください。非ネイティブ Java プログラミング言語のメソッドに対応するフレームだけが通知を受信できます。
指定したスレッドは現在のスレッドであるか、スレッドが中断したかのどちらかです。
|
名前
|
型
|
説明
|
thread | jthread |
フレームのポップイベントが生成されるフレームのスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
depth | jint |
フレームのポップイベントが生成されるフレームの深さ。
|
早期復帰の強制
早期復帰の強制の関数:
これらの関数を使うと、エージェントは、実行中の任意のポイントでの復帰をメソッドに強制できます。早期復帰するメソッドを「被呼び出しメソッド」と呼びます。被呼び出しメソッドは、『Java 仮想マシン仕様』の「Frames」セクションに定義されているとおり、関数の呼び出し時に、指定されたスレッドの現在のメソッドになります。
指定されたスレッドは、中断されているか、現在のスレッドでなければいけません。メソッドの復帰は、Java プログラミング言語のコードの実行がこのスレッド上で再開されたときに行われます。これらの関数のいずれかを呼び出してからスレッドの実行が再開されるまでの間のスタックの状態は未定義です。
被呼び出しメソッドでは、これ以上の命令は実行されません。特に、最終的にブロックは実行されません。注:これにより、アプリケーション内で整合性のない状態が発生することがあります。
被呼び出しメソッドを呼び出すことによって獲得されたロック (これが synchronized メソッドの場合) と、被呼び出しメソッド内の synchronized ブロックに入ることによって獲得されたロックは解放されます。注:これは、ネイティブロックや java.util.concurrent.locks ロックには適用されません。
通常復帰の場合と同様に、MethodExit などのイベントが生成されます。
被呼び出しメソッドは、非ネイティブの Java プログラミング言語のメソッドとします。スタック上にフレームが 1 つだけある状態でスレッドへの強制復帰を行なった場合、スレッドが再開時に終了します。
早期復帰の強制 - オブジェクト型
jvmtiError
ForceEarlyReturnObject(jvmtiEnv* env,
jthread thread,
jobject value)
この関数を使うと、結果の型が Object または Object のサブクラスであるメソッドから復帰できます。
|
名前
|
型
|
説明
|
thread | jthread |
現在のフレームが早期復帰するスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
value | jobject |
被呼び出しフレームの戻り値。オブジェクトまたは NULL。
|
早期復帰の強制 - 整数型
jvmtiError
ForceEarlyReturnInt(jvmtiEnv* env,
jthread thread,
jint value)
この関数を使うと、結果の型が int、short、char、byte、boolean のいずれかであるメソッドから復帰できます。
|
名前
|
型
|
説明
|
thread | jthread |
現在のフレームが早期復帰するスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
value | jint |
被呼び出しフレームの戻り値。
|
早期復帰の強制 - 長整数型
jvmtiError
ForceEarlyReturnLong(jvmtiEnv* env,
jthread thread,
jlong value)
この関数を使うと、結果の型が long であるメソッドから復帰できます。
|
名前
|
型
|
説明
|
thread | jthread |
現在のフレームが早期復帰するスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
value | jlong |
被呼び出しフレームの戻り値。
|
早期復帰の強制 - 浮動小数点数型
jvmtiError
ForceEarlyReturnFloat(jvmtiEnv* env,
jthread thread,
jfloat value)
この関数を使うと、結果の型が float であるメソッドから復帰できます。
|
名前
|
型
|
説明
|
thread | jthread |
現在のフレームが早期復帰するスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
value | jfloat |
被呼び出しフレームの戻り値。
|
早期復帰の強制 - 倍精度浮動小数点数型
jvmtiError
ForceEarlyReturnDouble(jvmtiEnv* env,
jthread thread,
jdouble value)
この関数を使うと、結果の型が double であるメソッドから復帰できます。
|
名前
|
型
|
説明
|
thread | jthread |
現在のフレームが早期復帰するスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
value | jdouble |
被呼び出しフレームの戻り値。
|
早期復帰の強制 - void 型
jvmtiError
ForceEarlyReturnVoid(jvmtiEnv* env,
jthread thread)
この関数を使うと、結果の型を持たないメソッドから復帰できます。つまり、被呼び出しメソッドが void と宣言されていなければいけません。
|
名前
|
型
|
説明
|
thread | jthread |
現在のフレームが早期復帰するスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
ヒープ
ヒープ関数:
ヒープの関数型:
ヒープの型:
ヒープのフラグおよび定数:
これらの関数は、ヒープの分析に使用されます。ヒープ内のオブジェクトの表示、これらのオブジェクトへのタグ付けなどの機能があります。
「タグ」は、オブジェクトに関連付けられる値です。タグは、エージェントにより、タグの設定関数を使って明示的に設定されます。または、jvmtiHeapIterationCallback などのコールバック関数によって設定されます。
タグは環境に対してローカルです。つまり、ある環境のタグを別の環境で表示することはできません。
タグは jlong 値です。この値を使って、オブジェクトにマークを付けたり、詳細情報のポインタを格納したりできます。タグ付けされていないオブジェクトには、ゼロのタグが付いています。タグをゼロに設定することにより、オブジェクトのタグ付けを解除できます。
ヒープコールバック関数
ヒープ関数は、ヒープ内での繰り返し処理とオブジェクト参照の再帰的な追跡を行い、エージェントが指定したコールバック関数を使って情報提供を行います。
これらのヒープコールバック関数は、次の制限に従います。これらのコールバックで JNI 関数は使用しないでください。これらのコールバックでは、特別に使用が許可されている「コールバック安全」な関数以外の JVM TI 関数を使用できません (raw モニター関数、メモリー管理関数、環境ローカル記憶領域関数を参照)。
実装は、内部スレッド上または繰り返し関数を呼び出したスレッド上で、コールバックを呼び出すことができます。ヒープコールバックはシングルスレッドです。複数のコールバックが同時に呼び出されることはありません。
ヒープフィルタフラグを使うと、オブジェクトまたはそのクラスのタグの状態に基づいて報告を行わないようにすることができます。フラグが設定されていない場合 (jint がゼロの場合)、オブジェクトのフィルタリングは行われません。
|
定数
|
値
|
説明
|
JVMTI_HEAP_FILTER_TAGGED | 0x4 |
タグ付きのオブジェクトをフィルタリングする。タグの付いたオブジェクトが除外される。
|
JVMTI_HEAP_FILTER_UNTAGGED | 0x8 |
タグなしのオブジェクトをフィルタリングする。タグの付いていないオブジェクトが除外される。
|
JVMTI_HEAP_FILTER_CLASS_TAGGED | 0x10 |
タグ付きのクラスを持つオブジェクトをフィルタリングする。タグの付いたクラスのオブジェクトが除外される。
|
JVMTI_HEAP_FILTER_CLASS_UNTAGGED | 0x2; |
タグなしのクラスを持つオブジェクトをフィルタリングする。タグの付いていないクラスのオブジェクトが除外される。
|
ヒープコールバックによって返されるヒープビジット制御フラグを使うと、繰り返し処理を中止できます。また、ヒープ参照コールバックは、トラバース対象となる参照のグラフを取り除くために使うこともできます (JVMTI_VISIT_OBJECTS を設定しない)。
|
定数
|
値
|
説明
|
JVMTI_VISIT_OBJECTS | 0x100 |
あるオブジェクトをビジットする際にこのコールバックが FollowReferences によって起動されたものであった場合、そのオブジェクトの参照をトラバースする。それ以外の場合は無視される。
|
JVMTI_VISIT_ABORT | 0x8000 |
繰り返し処理を中止。ほかのすべてのビットを無視する。
|
ヒープ参照の列挙は、報告対象の参照の種類を記述する目的で、ヒープ参照コールバックとプリミティブフィールドコールバックによって提供されます。
|
定数
|
値
|
説明
|
JVMTI_HEAP_REFERENCE_CLASS | 1 |
オブジェクトからそのクラスへの参照。
|
JVMTI_HEAP_REFERENCE_FIELD | 2 |
オブジェクトから、そのオブジェクトのいずれかのインスタンスフィールド値への参照。
|
JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT | 3 |
配列から、その配列のいずれかの要素への参照。
|
JVMTI_HEAP_REFERENCE_CLASS_LOADER | 4 |
クラスからそのクラスローダーへの参照。
|
JVMTI_HEAP_REFERENCE_SIGNERS | 5 |
クラスからその署名者の配列への参照。
|
JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN | 6 |
クラスからその保護ドメインへの参照。
|
JVMTI_HEAP_REFERENCE_INTERFACE | 7 |
クラスから、そのクラスのいずれかのインタフェースへの参照。注:インタフェースは定数プール参照経由で定義されるため、参照されたインタフェースは参照の種類が JVMTI_HEAP_REFERENCE_CONSTANT_POOL で報告される可能性もある。
|
JVMTI_HEAP_REFERENCE_STATIC_FIELD | 8 |
クラスからそのいずれかの static フィールド値への参照。
|
JVMTI_HEAP_REFERENCE_CONSTANT_POOL | 9 |
クラスから定数プール内の解決済みエントリへの参照。
|
JVMTI_HEAP_REFERENCE_SUPERCLASS | 10 |
クラスからそのスーパークラスへの参照。スーパークラスが java.lang.Object の場合、コールバックは送信されない。注:ロードされたクラスは定数プール参照経由でスーパークラスを定義するため、参照されたスーパークラスは参照の種類が JVMTI_HEAP_REFERENCE_CONSTANT_POOL で報告される可能性もある。
|
JVMTI_HEAP_REFERENCE_JNI_GLOBAL | 21 |
ヒープルート参照:JNI グローバル参照。
|
JVMTI_HEAP_REFERENCE_SYSTEM_CLASS | 22 |
ヒープルート参照:システムクラス。
|
JVMTI_HEAP_REFERENCE_MONITOR | 23 |
ヒープルート参照:モニター。
|
JVMTI_HEAP_REFERENCE_STACK_LOCAL | 24 |
ヒープルート参照:スタック上の局所変数。
|
JVMTI_HEAP_REFERENCE_JNI_LOCAL | 25 |
ヒープルート参照:JNI ローカル参照。
|
JVMTI_HEAP_REFERENCE_THREAD | 26 |
ヒープルート参照:スレッド。
|
JVMTI_HEAP_REFERENCE_OTHER | 27 |
ヒープルート参照:ほかのヒープルート参照。
|
プリミティブ型の単一文字型記述子の定義。
|
定数
|
値
|
説明
|
JVMTI_PRIMITIVE_TYPE_BOOLEAN | 90 |
「Z」 - Java プログラミング言語の boolean - JNI の jboolean
|
JVMTI_PRIMITIVE_TYPE_BYTE | 66 |
「B」 - Java プログラミング言語の byte - JNI の jbyte
|
JVMTI_PRIMITIVE_TYPE_CHAR | 67 |
「C」 - Java プログラミング言語の char - JNI の jchar
|
JVMTI_PRIMITIVE_TYPE_SHORT | 83 |
「S」 - Java プログラミング言語の short - JNI の jshort
|
JVMTI_PRIMITIVE_TYPE_INT | 73 |
「I」 - Java プログラミング言語の int - JNI の jint
|
JVMTI_PRIMITIVE_TYPE_LONG | 74 |
「J」 - Java プログラミング言語の long - JNI の jlong
|
JVMTI_PRIMITIVE_TYPE_FLOAT | 70 |
「F」 - Java プログラミング言語の float - JNI の jfloat
|
JVMTI_PRIMITIVE_TYPE_DOUBLE | 68 |
「D」 - Java プログラミング言語の double - JNI の jdouble
|
フィールド参照用の参照情報構造体
JVMTI_HEAP_REFERENCE_FIELD および JVMTI_HEAP_REFERENCE_STATIC_FIELD 参照に対して返される参照情報。
typedef struct {
jint index;
} jvmtiHeapReferenceInfoField;
|
フィールド
|
型
|
説明
|
index | jint |
JVMTI_HEAP_REFERENCE_FIELD の場合、参照側オブジェクトはクラスでもインタフェースでもありません。この場合、index は、参照側オブジェクトのクラスに含まれるフィールドのインデックスです。以降、このクラスを C と呼びます。
JVMTI_HEAP_REFERENCE_STATIC_FIELD の場合、参照側オブジェクトは、クラス (以降 C と呼ぶ) とインタフェース (以降 I と呼ぶ) のいずれかになります。この場合、index は、そのクラスまたはインタフェースに含まれるフィールドのインデックスです。
参照側オブジェクトがインタフェースでない場合、フィールドのインデックスは次のようにして決定されます。
- C とそのスーパークラスに含まれるすべてのフィールドのリストが作成されます。このリストは、
java.lang.Object 内のすべてのフィールドで始まり、C 内のすべてのフィールドで終わります。
- このリスト内で、指定されたクラスのフィールドが
GetClassFields から返された順番に並べられます。
- このリスト内のフィールドに、インデックス n、n+1、... が順に割り当てられます。n は、C が実装するすべてのインタフェースに含まれるフィールドのカウント数です。C は、そのスーパークラスが直接実装するすべてのインタフェースと、それらインタフェースのすべてのスーパーインタフェースを実装しています。
参照側オブジェクトがインタフェースである場合、フィールドのインデックスは次のようにして決定されます。
- I 内で直接宣言されているフィールドのリストが作成されます。
- このリスト内のフィールドが
GetClassFields から返された順番に並べられます。
- このリスト内のフィールドに、インデックス n、n+1、... が順に割り当てられます。n は、I のすべてのスーパーインタフェースに含まれるフィールドのカウント数です。
この計算には、フィールド修飾子 (static、public、private など) の種類にかかわらず、すべてのフィールドが含まれます。
たとえば、次のようなクラスとインタフェースが指定されているとします。
interface I0 {
int p = 0;
}
interface I1 extends I0 {
int x = 1;
}
interface I2 extends I0 {
int y = 2;
}
class C1 implements I1 {
public static int a = 3;
private int b = 4;
}
class C2 extends C1 implements I2 {
static int q = 5;
final int r = 6;
}
C1 で呼び出された GetClassFields から、C1 のフィールド a、b がこの順番で返され、C2 のフィールド q、r がこの順番で返されるものとします。クラス C1 のインスタンスのフィールドインデックスは、次のようになります。
-
|
a
|
2
|
C1 が実装するインタフェース内のフィールドのカウント数は 2 (n=2) です。つまり、I0 の p と I1 の x です。
|
|
b
|
3
|
後続のインデックス。
|
クラス C1 も同じフィールドインデックスを持ちます。
クラス C2 のインスタンスのフィールドインデックスは、次のようになります。
-
|
a
|
3
|
C2 が実装するインタフェース内のフィールドのカウント数は 3 (n=3) です。つまり、I0 の p、I1 の x、および I2 の y (C2 のインタフェース) です。I0 のフィールド p は一度しか含まれません。
|
|
b
|
4
|
「a」に続くインデックス。
|
|
q
|
5
|
「b」に続くインデックス。
|
|
r
|
6
|
「q」に続くインデックス。
|
クラス C2 も同じフィールドインデックスを持ちます。上記のフィールド「a」のように、同じフィールドが、参照側オブジェクトごとに異なるインデックスを持つ可能性があります。また、コールバックからすべてのフィールドインデックスが可視になるわけではありませんが、ここでは説明のためにすべてのインデックスを示しています。
インタフェース I1 も同じフィールドインデックスを持ちます。
-
|
x
|
1
|
I1 のスーパーインタフェース内のフィールドのカウント数は 1 (n=1) です。つまり、I0 の p です。
|
|
配列参照用の参照情報構造体
JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT 参照に対して返される参照情報。
typedef struct {
jint index;
} jvmtiHeapReferenceInfoArray;
|
フィールド
|
型
|
説明
|
index | jint |
配列のインデックス。
|
定数プール参照用の参照情報構造体
JVMTI_HEAP_REFERENCE_CONSTANT_POOL 参照に対して返される参照情報。
typedef struct {
jint index;
} jvmtiHeapReferenceInfoConstantPool;
局所変数参照用の参照情報構造体
JVMTI_HEAP_REFERENCE_STACK_LOCAL 参照に対して返される参照情報。
typedef struct {
jlong thread_tag;
jlong thread_id;
jint depth;
jmethodID method;
jlocation location;
jint slot;
} jvmtiHeapReferenceInfoStackLocal;
|
フィールド
|
型
|
説明
|
thread_tag | jlong |
このスタックに対応するスレッドのタグ。 タグ付けされていない場合はゼロ。
|
thread_id | jlong |
このスタックに対応するスレッドの一意のスレッド ID。
|
depth | jint |
フレームの深さ。
|
method | jmethodID |
このフレーム内で実行されているメソッド。
|
location | jlocation |
このフレーム内で現在実行されている位置。
|
slot | jint |
局所変数のスロット番号。
|
JNI ローカル参照用の参照情報構造体
JVMTI_HEAP_REFERENCE_JNI_LOCAL 参照に対して返される参照情報。
typedef struct {
jlong thread_tag;
jlong thread_id;
jint depth;
jmethodID method;
} jvmtiHeapReferenceInfoJniLocal;
|
フィールド
|
型
|
説明
|
thread_tag | jlong |
このスタックに対応するスレッドのタグ。 タグ付けされていない場合はゼロ。
|
thread_id | jlong |
このスタックに対応するスレッドの一意のスレッド ID。
|
depth | jint |
フレームの深さ。
|
method | jmethodID |
このフレーム内で実行されているメソッド。
|
その他の参照用の参照情報構造体
その他の参照に対して返される参照情報。
typedef struct {
jlong reserved1;
jlong reserved2;
jlong reserved3;
jlong reserved4;
jlong reserved5;
jlong reserved6;
jlong reserved7;
jlong reserved8;
} jvmtiHeapReferenceInfoReserved;
|
フィールド
|
型
|
説明
|
reserved1 | jlong |
将来の使用のために予約済み。
|
reserved2 | jlong |
将来の使用のために予約済み。
|
reserved3 | jlong |
将来の使用のために予約済み。
|
reserved4 | jlong |
将来の使用のために予約済み。
|
reserved5 | jlong |
将来の使用のために予約済み。
|
reserved6 | jlong |
将来の使用のために予約済み。
|
reserved7 | jlong |
将来の使用のために予約済み。
|
reserved8 | jlong |
将来の使用のために予約済み。
|
参照情報構造体
参照側に関して返される情報。各種参照情報の共用体として表されます。
typedef union {
jvmtiHeapReferenceInfoField field;
jvmtiHeapReferenceInfoArray array;
jvmtiHeapReferenceInfoConstantPool constant_pool;
jvmtiHeapReferenceInfoStackLocal stack_local;
jvmtiHeapReferenceInfoJniLocal jni_local;
jvmtiHeapReferenceInfoReserved other;
} jvmtiHeapReferenceInfo;
ヒープコールバック関数構造体
typedef struct {
jvmtiHeapIterationCallback heap_iteration_callback;
jvmtiHeapReferenceCallback heap_reference_callback;
jvmtiPrimitiveFieldCallback primitive_field_callback;
jvmtiArrayPrimitiveValueCallback array_primitive_value_callback;
jvmtiStringPrimitiveValueCallback string_primitive_value_callback;
jvmtiReservedCallback reserved5;
jvmtiReservedCallback reserved6;
jvmtiReservedCallback reserved7;
jvmtiReservedCallback reserved8;
jvmtiReservedCallback reserved9;
jvmtiReservedCallback reserved10;
jvmtiReservedCallback reserved11;
jvmtiReservedCallback reserved12;
jvmtiReservedCallback reserved13;
jvmtiReservedCallback reserved14;
jvmtiReservedCallback reserved15;
} jvmtiHeapCallbacks;
原理の説明:
ヒープダンプ機能 (下記) は、各オブジェクトにコールバックを使用します。バッファー方式のほうがスループットが高いように思われますが、テストでは、そのような結果は得られません。メモリー参照の場所または配列アクセスのオーバヘッドによるものと考えられます。
ヒープ繰り返しコールバック
typedef jint (JNICALL *jvmtiHeapIterationCallback)
(jlong class_tag,
jlong size,
jlong* tag_ptr,
jint length,
void* user_data);
エージェントによって提供されるコールバック関数。ヒープ内のオブジェクトを記述しますが、値は渡しません。
この関数は、必要なビジット制御フラグのビットベクトルを返します。これにより、繰り返し処理の全体を中止すべきかどうかが決まります (JVMTI_VISIT_OBJECTS フラグは無視される)。
ヒープコールバック関数の制限を参照してください。
|
名前
|
型
|
説明
|
class_tag | jlong |
オブジェクトのクラスのタグ (タグ付けされていないクラスの場合はゼロ)。オブジェクトが実行時クラスを表す場合、class_tag は java.lang.Class に関連付けされたタグ (java.lang.Class がタグ付けされていない場合はゼロ)。
|
size | jlong |
オブジェクトのサイズ (バイト単位)。GetObjectSize を参照。
|
tag_ptr | jlong* |
オブジェクトのタグ値。タグ付けされていないオブジェクトの場合はゼロ。オブジェクトと関連付けるタグの値を設定するため、エージェントはパラメータによってポイントされる jlong を設定する。
|
length | jint |
このオブジェクトが配列である場合はその配列の長さ。それ以外の場合はマイナス 1 (-1)。
|
user_data | void * |
ユーザーが入力し、繰り返し関数に渡されたデータ。
|
|
ヒープ参照コールバック
typedef jint (JNICALL *jvmtiHeapReferenceCallback)
(jvmtiHeapReferenceKind reference_kind,
const jvmtiHeapReferenceInfo* reference_info,
jlong class_tag,
jlong referrer_class_tag,
jlong size,
jlong* tag_ptr,
jlong* referrer_tag_ptr,
jint length,
void* user_data);
エージェントによって提供されるコールバック関数。あるオブジェクトまたは VM (参照側) から別のオブジェクト (参照先) への参照、またはあるヒープルートからある参照先への参照を記述します。
この関数は、必要なビジット制御フラグのビットベクトルを返します。これにより、参照先が参照しているオブジェクトをビジットすべきかどうかや、繰り返し処理の全体を中止すべきかどうかが決まります。
ヒープコールバック関数の制限を参照してください。
|
プリミティブフィールドコールバック
typedef jint (JNICALL *jvmtiPrimitiveFieldCallback)
(jvmtiHeapReferenceKind kind,
const jvmtiHeapReferenceInfo* info,
jlong object_class_tag,
jlong* object_tag_ptr,
jvalue value,
jvmtiPrimitiveType value_type,
void* user_data);
あるオブジェクト (「オブジェクト」) のプリミティブフィールドを記述する、エージェントによって提供されるコールバック関数。プリミティブフィールドとは、型がプリミティブ型であるフィールドのことです。このコールバックは、オブジェクトがクラスの場合は static フィールドを、それ以外の場合はインスタンスフィールドをそれぞれ記述します。
この関数は、必要なビジット制御フラグのビットベクトルを返します。これにより、繰り返し処理の全体を中止すべきかどうかが決まります (JVMTI_VISIT_OBJECTS フラグは無視される)。
ヒープコールバック関数の制限を参照してください。
|
配列プリミティブ値コールバック
typedef jint (JNICALL *jvmtiArrayPrimitiveValueCallback)
(jlong class_tag,
jlong size,
jlong* tag_ptr,
jint element_count,
jvmtiPrimitiveType element_type,
const void* elements,
void* user_data);
エージェントによって提供されるコールバック関数。あるプリミティブ型の配列内の値を記述します。
この関数は、必要なビジット制御フラグのビットベクトルを返します。これにより、繰り返し処理の全体を中止すべきかどうかが決まります (JVMTI_VISIT_OBJECTS フラグは無視される)。
ヒープコールバック関数の制限を参照してください。
|
名前
|
型
|
説明
|
class_tag | jlong |
配列オブジェクトのクラスのタグ (タグ付けされていないクラスの場合はゼロ)。
|
size | jlong |
配列のサイズ (バイト単位)。GetObjectSize を参照。
|
tag_ptr | jlong* |
配列オブジェクトのタグをポイントする。タグ付けされていないオブジェクトの場合はゼロをポイントする。オブジェクトと関連付けるタグの値を設定するため、エージェントはパラメータによってポイントされる jlong を設定する。
|
element_count | jint |
プリミティブ配列の長さ。
|
element_type | jvmtiPrimitiveType |
配列の要素の型。
|
elements | const void* |
配列の要素。この配列は、element_type のサイズを持つ element_count 個の項目から成るパック配列となる。
|
user_data | void * |
ユーザーが入力し、繰り返し関数に渡されたデータ。
|
|
文字列プリミティブ値コールバック
typedef jint (JNICALL *jvmtiStringPrimitiveValueCallback)
(jlong class_tag,
jlong size,
jlong* tag_ptr,
const jchar* value,
jint value_length,
void* user_data);
エージェントによって提供されるコールバック関数。java.lang.String の値を記述します。
この関数は、必要なビジット制御フラグのビットベクトルを返します。これにより、繰り返し処理の全体を中止すべきかどうかが決まります (JVMTI_VISIT_OBJECTS フラグは無視される)。
ヒープコールバック関数の制限を参照してください。
|
名前
|
型
|
説明
|
class_tag | jlong |
String クラスのクラスのタグ (タグ付けされていないクラスの場合はゼロ)。
|
size | jlong |
文字列のサイズ (バイト単位)。GetObjectSize を参照。
|
tag_ptr | jlong* |
String オブジェクトのタグをポイントする。タグ付けされていないオブジェクトの場合はゼロをポイントする。オブジェクトと関連付けるタグの値を設定するため、エージェントはパラメータによってポイントされる jlong を設定する。
|
value | const jchar* |
String の値。Unicode 文字列としてエンコードされる。
|
value_length | jint |
文字列の長さ。この長さは、文字列内の 16 ビット Unicode 文字の数に等しくなる。
|
user_data | void * |
ユーザーが入力し、繰り返し関数に渡されたデータ。
|
|
将来使用するために予約されたコールバック
typedef jint (JNICALL *jvmtiReservedCallback)
();
プレースホルダー -- 将来の使用のために予約済みです。
|
参照の追跡
jvmtiError
FollowReferences(jvmtiEnv* env,
jint heap_filter,
jclass klass,
jobject initial_object,
const jvmtiHeapCallbacks* callbacks,
const void* user_data)
この関数は、指定されたオブジェクトから直接的、間接的に到達可能なオブジェクトのトラバーサルを開始します。initial_object が指定されなかった場合は、ヒープルートから到達可能なすべてのオブジェクトが対象となります。ヒープルートは、システムクラス、JNI グローバル、スレッドスタックからの参照、ガベージコレクションの目的でルートとして使用されるその他のオブジェクトのセットです。
この関数は、参照グラフをトラバースすることで動作します。A、B、... がオブジェクトを表すとします。A から B への参照がトラバースされた場合、ヒープルートから B への参照がトラバースされた場合、または B が initial_object として指定された場合に、B が「ビジット」されたと言います。A から B への参照がトラバースされるのは、A のビジット後です。参照の報告順序は、参照のトラバース順序と同じになります。オブジェクト参照の報告は、エージェントから提供されるコールバック関数 jvmtiHeapReferenceCallback を呼び出すことで行われます。A から B への参照で、A は「参照側」、B は「参照先」と呼ばれます。コールバックは、参照側からの参照のたびに 1 回だけ呼び出されます。参照サイクルや、参照側のパスが複数存在する場合も同様です。参照側と参照先との間に参照が複数存在する可能性がありますが、その場合は、それぞれの参照が報告されます。これらの参照を区別するには、jvmtiHeapReferenceCallback コールバックの reference_kind および reference_info パラメータを確認します。
この関数が報告するのは、オブジェクト参照の Java プログラミング言語ビューであり、仮想マシン実装ビューではありません。null 以外の次のオブジェクト参照が報告されます。
- インスタンスオブジェクトは、各非プリミティブインスタンスフィールド (継承されたフィールドも含む) への参照を報告します。
- インスタンスオブジェクトは、そのオブジェクトの型 (クラス) への参照を報告します。
- クラスは、スーパークラスへの参照と、直接実装または拡張したインタフェースへの参照を報告します。
- クラスは、クラスローダー、保護ドメイン、署名者、および定数プール内の解決済みエントリへの参照を報告します。
- クラスは、直接宣言された各非プリミティブ static フィールドへの参照を報告します。
- 配列は、その配列の型 (クラス) と各配列要素への参照を報告する。
- プリミティブ配列は、その配列の型への参照を報告します。
また、この関数を使うと、プリミティブ (オブジェクト以外) 値を調べることもできます。配列または String のプリミティブ値の報告は、オブジェクトのビジットの完了後に行われます。その報告時には、エージェントが提供するコールバック関数 jvmtiArrayPrimitiveValueCallback または jvmtiStringPrimitiveValueCallback が呼び出されます。あるプリミティブフィールドの報告は、そのフィールドを含むオブジェクトのビジットの完了後に行われます。その報告時には、エージェントが提供するコールバック関数 jvmtiPrimitiveFieldCallback が呼び出されます。
コールバックが提供されるか NULL であるかは、そのコールバックが呼び出されるかどうかだけを決定します。どのオブジェクトがビジットされるかや、ほかのコールバックが呼び出されるかどうかに影響を与えることはありません。ただし、jvmtiHeapReferenceCallback から返されるビジット制御フラグは、現在のオブジェクトが参照しているオブジェクトをビジットするかどうかを決定します。この関数のパラメータとして指定されるヒープフィルタフラグと klass は、ビジットされるオブジェクトは制御しませんが、コールバックによって報告されるオブジェクトおよびプリミティブ値は制御します。たとえば、設定された唯一のコールバックが配列プリミティブ値コールバックであり、klass がバイト配列のクラスに設定された場合、バイト配列のみが報告されます。以上をまとめたのが次の表です。
この関数の実行中、ヒープのステータスは変化しません。オブジェクトの割り当てやガベージコレクションは行われません。よって、オブジェクト (格納されている値も含む) は変更されません。結果として、Java プログラミング言語のコードを実行するスレッド、Java プログラミング言語のコードの実行を再開しようとしているスレッド、JNI 関数を実行しようとしているスレッドは、停止します。
|
名前
|
型
|
説明
|
heap_filter | jint |
このヒープフィルタフラグのビットベクトルは、コールバック関数の呼び出し対象となるオブジェクトを制限する。これはオブジェクトコールバックとプリミティブコールバックの両方に当てはまる。
|
klass | jclass
|
コールバックが報告するのは、オブジェクトがこのクラスのインスタンスである場合だけである。オブジェクトが klass のスーパークラスのインスタンスである場合、そのオブジェクトは報告されない。klass がインタフェースの場合、オブジェクトの報告は行われない。これはオブジェクトコールバックとプリミティブコールバックの両方に当てはまる。
klass が NULL の場合、コールバックは特定のクラスのインスタンスに制限されない。
|
initial_object | jobject
|
追跡するオブジェクト
initial_object が NULL の場合、ヒープルートから参照の追跡が行われる。
|
callbacks | const jvmtiHeapCallbacks * |
一連のコールバック関数を定義する構造体。
エージェントは jvmtiHeapCallbacks にポインタを渡す。 |
user_data | const void
* |
ユーザーが入力し、コールバックに渡されるデータ。
エージェントがポインタを渡す。user_data が NULL の場合、NULL がユーザー指定データとして渡される。
|
ヒープ内での繰り返し
jvmtiError
IterateThroughHeap(jvmtiEnv* env,
jint heap_filter,
jclass klass,
const jvmtiHeapCallbacks* callbacks,
const void* user_data)
ヒープ内のすべてのオブジェクトに対する繰り返し処理を起動します。到達可能なオブジェクトも、そうで ないオブジェクトも含まれます。オブジェクトのビジットは特定の順番では行われません。
ヒープオブジェクトの報告は、エージェントから提供されるコールバック関数 jvmtiHeapIterationCallback を呼び出すことで行われます。オブジェクト間の参照は報告されません。到達可能なオブジェクトのみが必要である場合や、オブジェクト参照の情報が必要である場合には、FollowReferences を使用してください。
また、この関数を使うと、プリミティブ (オブジェクト以外) 値を調べることもできます。配列または String のプリミティブ値の報告は、オブジェクトのビジットの完了後に行われます。その報告時には、エージェントが提供するコールバック関数 jvmtiArrayPrimitiveValueCallback または jvmtiStringPrimitiveValueCallback が呼び出されます。あるプリミティブフィールドの報告は、そのフィールドを含むオブジェクトのビジットの完了後に行われます。その報告時には、エージェントが提供するコールバック関数 jvmtiPrimitiveFieldCallback が呼び出されます。
コールバックから返されるヒープビジット制御フラグによって繰り返し処理が中止されないかぎり、ヒープ内のすべてのオブジェクトがビジットされます。コールバックが提供されるか NULL であるかは、そのコールバックが呼び出されるかどうかだけを決定します。どのオブジェクトがビジットされるかや、ほかのコールバックが呼び出されるかどうかに影響を与えることはありません。この関数のパラメータとして指定されるヒープフィルタフラグと klass は、ビジットされるオブジェクトは制御しませんが、コールバックによって報告されるオブジェクトおよびプリミティブ値は制御します。たとえば、設定された唯一のコールバックが配列プリミティブ値コールバックであり、klass がバイト配列のクラスに設定された場合、バイト配列のみが報告されます。以上をまとめたのが次の表です。これを FollowReferences と比較してください。
この関数の実行中、ヒープのステータスは変化しません。オブジェクトの割り当てやガベージコレクションは行われません。よって、オブジェクト (格納されている値も含む) は変更されません。結果として、Java プログラミング言語のコードを実行するスレッド、Java プログラミング言語のコードの実行を再開しようとしているスレッド、JNI 関数を実行しようとしているスレッドは、停止します。
|
名前
|
型
|
説明
|
heap_filter | jint |
このヒープフィルタフラグのビットベクトルは、コールバック関数の呼び出し対象となるオブジェクトを制限する。これはオブジェクトコールバックとプリミティブコールバックの両方に当てはまる。
|
klass | jclass
|
コールバックが報告するのは、オブジェクトがこのクラスのインスタンスである場合だけである。オブジェクトが klass のスーパークラスのインスタンスである場合、そのオブジェクトは報告されない。klass がインタフェースの場合、オブジェクトの報告は行われない。これはオブジェクトコールバックとプリミティブコールバックの両方に当てはまる。
klass が NULL の場合、コールバックは特定のクラスのインスタンスに制限されない。
|
callbacks | const jvmtiHeapCallbacks * |
一連のコールバック関数を定義する構造体。
エージェントは jvmtiHeapCallbacks にポインタを渡す。 |
user_data | const void
* |
ユーザーが入力し、コールバックに渡されるデータ。
エージェントがポインタを渡す。user_data が NULL の場合、NULL がユーザー指定データとして渡される。
|
タグの取得
jvmtiError
GetTag(jvmtiEnv* env,
jobject object,
jlong* tag_ptr)
オブジェクトに関連付けられたタグを取得します。タグは長整数値で、通常、オブジェクト情報の一意の識別子またはポインタを格納するために使用されます。タグの設定には、SetTag 関数を使用します。タグが設定されていないオブジェクトは、タグ値としてゼロを返します。
|
名前
|
型
|
説明
|
object | jobject |
タグが取得されるオブジェクト。
|
tag_ptr | jlong* |
戻ったとき、参照される長整数値にタグ値が設定されている。
エージェントは jlong にポインタを渡す。戻ったとき、jlong が設定されている。 |
タグの設定
jvmtiError
SetTag(jvmtiEnv* env,
jobject object,
jlong tag)
オブジェクトに関連付けられたタグを設定します。タグは長整数値で、通常、オブジェクト情報の一意の識別子またはポインタを格納するために使用されます。タグの表示には、GetTag 関数を使用します。
タグを使ったオブジェクトの取得
jvmtiError
GetObjectsWithTags(jvmtiEnv* env,
jint tag_count,
const jlong* tags,
jint* count_ptr,
jobject** object_result_ptr,
jlong** tag_result_ptr)
ヒープ内の指定されたタグを持つオブジェクトを返します。オブジェクトとタグの並行配列の形式になります。
|
名前
|
型
|
説明
|
tag_count | jint |
走査するタグの数。
|
tags | const jlong * |
これらのタグが付けられたオブジェクトを走査する。この配列内では、ゼロは使用できない。
エージェントは jlong の tag_count 要素の配列を渡す。 |
count_ptr | jint* |
tags 内の任意のタグを持つオブジェクトの数を返す。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
object_result_ptr | jobject
** |
tags 内の任意のタグを持つオブジェクトの配列を返す。
エージェントは jobject* にポインタを渡す。戻ったとき、jobject* は、サイズ *count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。object_result_ptr が NULL の場合、この情報は返されない。object_result_ptr から返されるオブジェクトは JNI ローカル参照であり、管理する必要がある。
|
tag_result_ptr | jlong
** |
object_result_ptr 内の各オブジェクトに対して、対応するインデックスのタグを返す。
エージェントは jlong* にポインタを渡す。戻ったとき、jlong* は、サイズ *count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。tag_result_ptr が NULL の場合、この情報は返されない。
|
ガベージコレクションの強制
jvmtiError
ForceGarbageCollection(jvmtiEnv* env)
VM にガベージコレクションの実行を強制します。ガベージコレクションは可能なかぎり完全に行われます。この関数は、ファイナライザを実行させません。この関数は、ガベージコレクションが完了するまで終了しません。
ガベージコレクションは可能な限り完全に実行されますが、この関数が戻るまでにすべての ObjectFree イベントが送信されているという保証はありません。特に、ファイナライズ待ちのオブジェクトが解放されない可能性があります。
ヒープ (1.0)
ヒープ (1.0) の関数:
ヒープ (1.0) の関数型:
ヒープ (1.0) の型:
これらの関数およびデータ型は元の JVM TI Version 1.0 で導入されたものであり、より 強力で柔軟性の高いバージョンで置き換えられました。新しいバージョンの特徴を次に示します。
-
プリミティブ値 (Strings、配列、およびプリミティブフィールドの値) へのアクセスを可能にする
-
参照側のタグを設定できるようにする。このため、より効率的なローカライズされた参照グラフの構築が可能となる
-
より広範なフィルタリング機能を提供する
-
拡張可能である。このため、JVM TI の将来のバージョンで拡張を施すことができる
現在のヒープ関数を使用してください。
|
定数
|
値
|
説明
|
JVMTI_HEAP_OBJECT_TAGGED | 1 |
タグ付きオブジェクトのみ。
|
JVMTI_HEAP_OBJECT_UNTAGGED | 2 |
タグなしオブジェクトのみ。
|
JVMTI_HEAP_OBJECT_EITHER | 3 |
タグ付きオブジェクトまたはタグなしオブジェクト。
|
|
定数
|
値
|
説明
|
JVMTI_HEAP_ROOT_JNI_GLOBAL | 1 |
JNI グローバル参照。
|
JVMTI_HEAP_ROOT_SYSTEM_CLASS | 2 |
システムクラス。
|
JVMTI_HEAP_ROOT_MONITOR | 3 |
モニター。
|
JVMTI_HEAP_ROOT_STACK_LOCAL | 4 |
スタックローカル。
|
JVMTI_HEAP_ROOT_JNI_LOCAL | 5 |
JNI ローカル参照。
|
JVMTI_HEAP_ROOT_THREAD | 6 |
スレッド
|
JVMTI_HEAP_ROOT_OTHER | 7 |
その他。
|
|
定数
|
値
|
説明
|
JVMTI_REFERENCE_CLASS | 1 |
オブジェクトからそのクラスの参照。
|
JVMTI_REFERENCE_FIELD | 2 |
オブジェクトから、そのオブジェクトのいずれかのインスタンスフィールドの値への参照。この種の参照の場合、jvmtiObjectReferenceCallback の referrer_index パラメータはインスタンスフィールドのインデックス。インデックスは、すべてのオブジェクトのフィールドの順序が基になる。クラスで直接宣言された static およびインスタンスフィールドが含まれるほか、スーパークラスおよびスーパーインタフェースで宣言されたすべてのフィールド (public と private の両方) が含まれる。そのためインデックスは、直接宣言されたクラスにあるフィールドのインデックス (「GetClassFields」 参照) と、すべてのスーパークラスおよびスーパーインタフェースで宣言されたフィールド (public と private の両方) を足し合わせたもので計算される。インデックスは 0 から始まる。
|
JVMTI_REFERENCE_ARRAY_ELEMENT | 3 |
配列から、この配列のいずれかの要素への参照。この種の参照の場合、jvmtiObjectReferenceCallback の referrer_index パラメータは配列のインデックス。
|
JVMTI_REFERENCE_CLASS_LOADER | 4 |
クラスからそのクラスローダーへの参照。
|
JVMTI_REFERENCE_SIGNERS | 5 |
クラスからその署名者の配列への参照。
|
JVMTI_REFERENCE_PROTECTION_DOMAIN | 6 |
クラスからその保護ドメインへの参照。
|
JVMTI_REFERENCE_INTERFACE | 7 |
クラスから、そのクラスのいずれかのインタフェースへの参照。
|
JVMTI_REFERENCE_STATIC_FIELD | 8 |
クラスから、そのクラスのいずれかの static フィールドの値への参照。この種の参照の場合、jvmtiObjectReferenceCallback の referrer_index パラメータは static フィールドのインデックス。インデックスは、すべてのオブジェクトのフィールドの順序が基になる。クラスで直接宣言された static およびインスタンスフィールドが含まれるほか、スーパークラスおよびスーパーインタフェースで宣言されたすべてのフィールド (public と private の両方) が含まれる。そのためインデックスは、直接宣言されたクラスにあるフィールドのインデックス (「GetClassFields」 参照) と、すべてのスーパークラスおよびスーパーインタフェースで宣言されたフィールド (public と private の両方) を足し合わせたもので計算される。インデックスは 0 から始まる。注:この定義は、JVM TI 1.0 仕様での定義と異なる。
原理の説明:既知の実装のなかで、1.0 の定義を使用したものはない。
|
JVMTI_REFERENCE_CONSTANT_POOL | 9 |
クラスから定数プール内の解決済みエントリの参照。この種の参照の場合、jvmtiObjectReferenceCallback の referrer_index パラメータは、クラスの定数プールテーブルのインデックスで、1 から始まる。『Java 仮想マシン仕様』の「Constant Pool」セクションを参照。
|
|
定数
|
値
|
説明
|
JVMTI_ITERATION_CONTINUE | 1 |
繰り返し処理を継続。参照の繰り返し処理の場合、このオブジェクトの参照に従う。
|
JVMTI_ITERATION_IGNORE | 2 |
繰り返し処理を継続。参照の繰り返し処理の場合、このオブジェクトの参照を無視する。
|
JVMTI_ITERATION_ABORT | 0 |
繰り返し処理を中止。
|
ヒープオブジェクトのコールバック
typedef jvmtiIterationControl (JNICALL *jvmtiHeapObjectCallback)
(jlong class_tag,
jlong size,
jlong* tag_ptr,
void* user_data);
エージェントによって提供されるコールバック関数。ヒープ内のオブジェクトを記述しますが、値は渡しません。
繰り返し処理を継続する場合、戻り値は JVMTI_ITERATION_CONTINUE です。繰り返し処理を停止する場合、戻り値は JVMTI_ITERATION_ABORT です。
ヒープコールバック関数の制限を参照してください。
|
名前
|
型
|
説明
|
class_tag | jlong |
オブジェクトのクラスのタグ (タグ付けされていないクラスの場合はゼロ)。オブジェクトが実行時クラスを表す場合、class_tag は java.lang.Class に関連付けされたタグ (java.lang.Class がタグ付けされていない場合はゼロ)。
|
size | jlong |
オブジェクトのサイズ (バイト単位)。GetObjectSize を参照。
|
tag_ptr | jlong* |
オブジェクトのタグ値。タグ付けされていないオブジェクトの場合はゼロ。オブジェクトと関連付けるタグの値を設定するため、エージェントはパラメータによってポイントされる jlong を設定する。
|
user_data | void * |
ユーザーが入力し、繰り返し関数に渡されたデータ。
|
|
ヒープルートオブジェクトのコールバック
typedef jvmtiIterationControl (JNICALL *jvmtiHeapRootCallback)
(jvmtiHeapRootKind root_kind,
jlong class_tag,
jlong size,
jlong* tag_ptr,
void* user_data);
エージェントによって提供されるコールバック関数。ガベージコレクションの目的で、ルートオブジェクトについて説明しますが、値は渡しません。
繰り返し処理を継続する場合、戻り値は JVMTI_ITERATION_CONTINUE です。 参照オブジェクトからの参照を続行しないで繰り返し処理を継続する場合、戻り値は JVMTI_ITERATION_IGNORE です。 繰り返し処理を停止する場合、戻り値は JVMTI_ITERATION_ABORT です。
ヒープコールバック関数の制限を参照してください。
|
名前
|
型
|
説明
|
root_kind | jvmtiHeapRootKind |
ヒープルートの種類
|
class_tag | jlong |
オブジェクトのクラスのタグ (タグ付けされていないクラスの場合はゼロ)。オブジェクトが実行時クラスを表す場合、class_tag は java.lang.Class に関連付けされたタグ (java.lang.Class がタグ付けされていない場合はゼロ)。
|
size | jlong |
オブジェクトのサイズ (バイト単位)。GetObjectSize を参照。
|
tag_ptr | jlong* |
オブジェクトのタグ値。タグ付けされていないオブジェクトの場合はゼロ。オブジェクトと関連付けるタグの値を設定するため、エージェントはパラメータによってポイントされる jlong を設定する。
|
user_data | void * |
ユーザーが入力し、繰り返し関数に渡されたデータ。
|
|
スタック参照オブジェクトのコールバック
typedef jvmtiIterationControl (JNICALL *jvmtiStackReferenceCallback)
(jvmtiHeapRootKind root_kind,
jlong class_tag,
jlong size,
jlong* tag_ptr,
jlong thread_tag,
jint depth,
jmethodID method,
jint slot,
void* user_data);
エージェントによって提供されるコールバック関数。ガベージコレクションの目的で、スタック上のルートオブジェクトについて説明しますが、値は渡しませ ん。
繰り返し処理を継続する場合、戻り値は JVMTI_ITERATION_CONTINUE です。 参照オブジェクトからの参照を続行しないで繰り返し処理を継続する場合、戻り値は JVMTI_ITERATION_IGNORE です。 繰り返し処理を停止する場合、戻り値は JVMTI_ITERATION_ABORT です。
ヒープコールバック関数の制限を参照してください。
|
名前
|
型
|
説明
|
root_kind | jvmtiHeapRootKind |
ルートの種類 (JVMTI_HEAP_ROOT_STACK_LOCAL または JVMTI_HEAP_ROOT_JNI_LOCAL)。
|
class_tag | jlong |
オブジェクトのクラスのタグ (タグ付けされていないクラスの場合はゼロ)。オブジェクトが実行時クラスを表す場合、class_tag は java.lang.Class に関連付けされたタグ (java.lang.Class がタグ付けされていない場合はゼロ)。
|
size | jlong |
オブジェクトのサイズ (バイト単位)。GetObjectSize を参照。
|
tag_ptr | jlong* |
オブジェクトのタグ値。タグ付けされていないオブジェクトの場合はゼロ。オブジェクトと関連付けるタグの値を設定するため、エージェントはパラメータによってポイントされる jlong を設定する。
|
thread_tag | jlong |
このスタックに対応するスレッドのタグ。タグ付けされていない場合はゼロ。
|
depth | jint |
フレームの深さ。
|
method | jmethodID |
このフレーム内で実行されているメソッド。
|
slot | jint |
スロット番号。
|
user_data | void * |
ユーザーが入力し、繰り返し関数に渡されたデータ。
|
|
オブジェクト参照のコールバック
typedef jvmtiIterationControl (JNICALL *jvmtiObjectReferenceCallback)
(jvmtiObjectReferenceKind reference_kind,
jlong class_tag,
jlong size,
jlong* tag_ptr,
jlong referrer_tag,
jint referrer_index,
void* user_data);
エージェントによって提供されるコールバック関数。あるオブジェクト (参照側) から別のオブジェクト (参照先) の参照について説明します。
繰り返し処理を継続する場合、戻り値は JVMTI_ITERATION_CONTINUE です。 参照オブジェクトからの参照を続行しないで繰り返し処理を継続する場合、戻り値は JVMTI_ITERATION_IGNORE です。 繰り返し処理を停止する場合、戻り値は JVMTI_ITERATION_ABORT です。
ヒープコールバック関数の制限を参照してください。
|
名前
|
型
|
説明
|
reference_kind | jvmtiObjectReferenceKind |
参照型。
|
class_tag | jlong |
参照されるオブジェクトのクラスのタグ (タグ付けされていないクラスの場合はゼロ)。参照されたオブジェクトが実行時クラスを表す場合、class_tag は java.lang.Class に関連付けされたタグ (java.lang.Class がタグ付けされていない場合はゼロ)。
|
size | jlong |
参照されるオブジェクトのサイズ (バイト単位)。GetObjectSize を参照。
|
tag_ptr | jlong* |
参照されるオブジェクトのタグ値。 タグ付けされていないオブジェクトの場合はゼロ。オブジェクトと関連付けるタグの値を設定するため、エージェントはパラメータによってポイントされる jlong を設定する。
|
referrer_tag | jlong |
参照側のオブジェクトのタグ値。 タグ付けされていないオブジェクトの場合はゼロ。
|
referrer_index | jint |
JVMTI_REFERENCE_FIELD 型または JVMTI_REFERENCE_STATIC_FIELD 型の参照の場合、参照側オブジェクトのフィールドのインデックス。インデックスはオブジェクトのすべてのフィールドの順序が基になる。詳細な説明については、JVMTI_REFERENCE_FIELD または JVMTI_REFERENCE_STATIC_FIELD を参照。
型 JVMTI_REFERENCE_ARRAY_ELEMENT の参照の場合は、配列インデックス。詳細な説明については、JVMTI_REFERENCE_ARRAY_ELEMENT を参照。
型 JVMTI_REFERENCE_CONSTANT_POOL の参照の場合は、クラスの定数プールに対するインデックス。 詳細な説明については、JVMTI_REFERENCE_CONSTANT_POOL を参照。
その他の参照の場合、referrer_index は -1。
|
user_data | void * |
ユーザーが入力し、繰り返し関数に渡されたデータ。
|
|
オブジェクトから到達可能なオブジェクトの繰り返し
jvmtiError
IterateOverObjectsReachableFromObject(jvmtiEnv* env,
jobject object,
jvmtiObjectReferenceCallback object_reference_callback,
const void* user_data)
この関数は、指定されたオブジェクトから直接または間接的に到達可能なすべてのオブジェクトに対して繰り返し処理を行います。オブジェクト B を参照する各オブジェクト A (参照側オブジェクト) に対して、指定されたコールバック関数が呼び出され、オブジェクト参照について説明します。コールバックは、参照側からの参照のたびに 1 回だけ呼び出されます。参照サイクルや、参照側のパスが複数存在する場合も同様です。参照側と参照される側の間に、複数の参照が存在する場合があります。これらの識別には、jvmtiObjectReference.reference_ (種類) と jvmtiObjectReference.referrer_ (インデックス) を使用します。オブジェクトのコールバックは、常に参照側のコールバックのあとで行われます。
報告されるオブジェクト参照については、FollowReferences を参照してください。
この関数の実行中、ヒープのステータスは変化しません。オブジェクトの割り当てやガベージコレクションは行われません。よって、オブジェクト (格納されている値も含む) は変更されません。結果として、Java プログラミング言語のコードを実行するスレッド、Java プログラミング言語のコードの実行を再開しようとしているスレッド、JNI 関数を実行しようとしているスレッドは、停止します。
|
名前
|
型
|
説明
|
object | jobject |
オブジェクト
|
object_reference_callback | jvmtiObjectReferenceCallback |
各オブジェクト参照を記述するために呼び出されるコールバック。
|
user_data | const void
* |
ユーザーが入力し、コールバックに渡されるデータ。
エージェントがポインタを渡す。user_data が NULL の場合、NULL がユーザー指定データとして渡される。
|
到達可能なオブジェクトの繰り返し
jvmtiError
IterateOverReachableObjects(jvmtiEnv* env,
jvmtiHeapRootCallback heap_root_callback,
jvmtiStackReferenceCallback stack_ref_callback,
jvmtiObjectReferenceCallback object_ref_callback,
const void* user_data)
この関数は、ルートオブジェクトと、ルートオブジェクトから直接または間接的に到達可能なすべてのオブジェクトに対して繰り返し処理を行います。ルートオ ブジェクトは、システムクラス、JNI グローバル、スレッドスタックからの参照、ガベージコレクションの目的でルートとして使用されるその他のオブジェクトのセットで構成されます。
各ルートに、heap_root_callbackま たはstack_root_callbackが 呼び出されます。オブジェクトは、1 つ以上の理由でルートオブジェクトになることができます。この場合、個々の理由に対して適切なコールバックが呼び出されます。
各オブジェクト参照に、object_ref_callback関数が呼び出され、オブジェクト参照について説明します。コールバックは、参照側からの参照のたびに 1 回だけ呼び出されます。参照サイクルや、参照側のパスが複数存在する場合も同様です。参照側と参照される側の間に、複数の参照が存在する場合があります。これらの識別には、jvmtiObjectReference.reference_ (種類) と jvmtiObjectReference.referrer_ (インデックス) を使用します。オブジェクトのコールバックは、常に参照側のコールバックのあとで行われます。
報告されるオブジェクト参照については、FollowReferences を参照してください。
ルートは、常に、オブジェクト参照が報告される前に、プロファイラに報告されます。つまり、object_ref_callbackは、すべてのルートに対して適切なコールバックが呼び出されるまで、呼び出されません。object_ref_callbackが NULL と指定されている場合、この関数は、プロファイラにルートオブジェクトを報告したあと、終了します。
この関数の実行中、ヒープのステータスは変化しません。オブジェクトの割り当てやガベージコレクションは行われません。よって、オブジェクト (格納されている値も含む) は変更されません。結果として、Java プログラミング言語のコードを実行するスレッド、Java プログラミング言語のコードの実行を再開しようとしているスレッド、JNI 関数を実行しようとしているスレッドは、停止します。
|
名前
|
型
|
説明
|
heap_root_callback | jvmtiHeapRootCallback
|
JVMTI_HEAP_ROOT_JNI_GLOBAL、JVMTI_HEAP_ROOT_SYSTEM_CLASS、JVMTI_HEAP_ROOT_MONITOR、JVMTI_HEAP_ROOT_THREAD、または JVMTI_HEAP_ROOT_OTHER 型の各ヒープルートのために呼び出されるコールバック関数。
heap_root_callback が NULL の場合、ヒープルートの報告は行わない。
|
stack_ref_callback | jvmtiStackReferenceCallback
|
JVMTI_HEAP_ROOT_STACK_LOCAL または JVMTI_HEAP_ROOT_JNI_LOCAL の各ヒープルートのために呼び出されるコールバック関数。
stack_ref_callback が NULL の場合、スタック参照の報告は行わない。
|
object_ref_callback | jvmtiObjectReferenceCallback
|
各オブジェクト参照のために呼び出されるコールバック。
object_ref_callback が NULL の場合、ルートオブジェクトからの参照には従わない。
|
user_data | const void
* |
ユーザーが入力し、コールバックに渡されるデータ。
エージェントがポインタを渡す。user_data が NULL の場合、NULL がユーザー指定データとして渡される。
|
ヒープの繰り返し
jvmtiError
IterateOverHeap(jvmtiEnv* env,
jvmtiHeapObjectFilter object_filter,
jvmtiHeapObjectCallback heap_object_callback,
const void* user_data)
ヒープ内のすべてのオブジェクトに対して繰り返し処理を行います。到達可能なオブジェクトも、そうで ないオブジェクトも含まれます。
object_filter パラメータは、どのオブジェクトのためにコールバック関数が呼び出されるかを示します。パラメータが JVMTI_HEAP_OBJECT_TAGGED の場合、コールバックは、すべてのタグ付きオブジェクトに対してのみ呼び出されます。パラメータが JVMTI_HEAP_OBJECT_UNTAGGED の場合、コールバックは、すべてのタグなしオブジェクトに対してのみ呼び出されます。パラメータが JVMTI_HEAP_OBJECT_EITHER の場合、コールバックは、タグが付いているかどうかに関係なく、ヒープ内のすべてのオブジェクトに対して呼び出されます。
この関数の実行中、ヒープのステータスは変化しません。オブジェクトの割り当てやガベージコレクションは行われません。よって、オブジェクト (格納されている値も含む) は変更されません。結果として、Java プログラミング言語のコードを実行するスレッド、Java プログラミング言語のコードの実行を再開しようとしているスレッド、JNI 関数を実行しようとしているスレッドは、停止します。
クラスのインスタンスの繰り返し
jvmtiError
IterateOverInstancesOfClass(jvmtiEnv* env,
jclass klass,
jvmtiHeapObjectFilter object_filter,
jvmtiHeapObjectCallback heap_object_callback,
const void* user_data)
指定されたクライアントのインスタンスになっている、ヒープ内のすべてのオブジェクトに対して繰り返し処理を行います。これには、指定されたクラスの直接のインスタンスと、指定されたクラスのすべてのサブクラスのインスタンスが含まれます。到達可能なオブジェクトも、そうで ないオブジェクトも含まれます。
object_filter パラメータは、どのオブジェクトのためにコールバック関数が呼び出されるかを示します。パラメータが JVMTI_HEAP_OBJECT_TAGGED の場合、コールバックは、すべてのタグ付きオブジェクトに対してのみ呼び出されます。パラメータが JVMTI_HEAP_OBJECT_UNTAGGED の場合、コールバックは、すべてのタグなしオブジェクトに対してのみ呼び出されます。パラメータが JVMTI_HEAP_OBJECT_EITHER の場合、コールバックは、タグが付いているかどうかに関係なく、ヒープ内のすべてのオブジェクトに対して呼び出されます。
この関数の実行中、ヒープのステータスは変化しません。オブジェクトの割り当てやガベージコレクションは行われません。よって、オブジェクト (格納されている値も含む) は変更されません。結果として、Java プログラミング言語のコードを実行するスレッド、Java プログラミング言語のコードの実行を再開しようとしているスレッド、JNI 関数を実行しようとしているスレッドは、停止します。
局所変数
局所変数関数:
これらの関数は、局所変数の値を取得または設定するために使います。変数は、変数の値を含んでいるフレームの深さと、そのフレーム内の変数のスロット番号によって識別されます。変数からスロット番号へのマッピングは、関数 GetLocalVariableTable を使って取得できます。
局所変数の取得 - オブジェクト型
jvmtiError
GetLocalObject(jvmtiEnv* env,
jthread thread,
jint depth,
jint slot,
jobject* value_ptr)
この関数を使うと、型が Object または Object のサブクラスである局所変数の値を取得できます。
|
名前
|
型
|
説明
|
thread | jthread |
変数の値を含むフレームのスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
depth | jint |
変数の値を含むフレームの深さ。
|
slot | jint |
変数のスロット番号。
|
value_ptr | jobject* |
戻ったとき、変数の値をポイントする。
エージェントは jobject にポインタを渡す。戻ったとき、jobject が設定されている。value_ptr から返されるオブジェクトは JNI ローカル参照であり、管理する必要がある。
|
局所変数の取得 - 整数型
jvmtiError
GetLocalInt(jvmtiEnv* env,
jthread thread,
jint depth,
jint slot,
jint* value_ptr)
この関数を使うと、型が int、short、char、byte、boolean のいずれかである局所変数の値を取得できます。
|
名前
|
型
|
説明
|
thread | jthread |
変数の値を含むフレームのスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
depth | jint |
変数の値を含むフレームの深さ。
|
slot | jint |
変数のスロット番号。
|
value_ptr | jint* |
戻ったとき、変数の値をポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
局所変数の取得 - 長整数型
jvmtiError
GetLocalLong(jvmtiEnv* env,
jthread thread,
jint depth,
jint slot,
jlong* value_ptr)
この関数を使うと、型が long である局所変数の値を取得できます。
|
名前
|
型
|
説明
|
thread | jthread |
変数の値を含むフレームのスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
depth | jint |
変数の値を含むフレームの深さ。
|
slot | jint |
変数のスロット番号。
|
value_ptr | jlong* |
戻ったとき、変数の値をポイントする。
エージェントは jlong にポインタを渡す。戻ったとき、jlong が設定されている。 |
局所変数の取得 - 浮動小数点数型
jvmtiError
GetLocalFloat(jvmtiEnv* env,
jthread thread,
jint depth,
jint slot,
jfloat* value_ptr)
この関数を使うと、型が float である局所変数の値を取得できます。
|
名前
|
型
|
説明
|
thread | jthread |
変数の値を含むフレームのスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
depth | jint |
変数の値を含むフレームの深さ。
|
slot | jint |
変数のスロット番号。
|
value_ptr | jfloat* |
戻ったとき、変数の値をポイントする。
エージェントは jfloat にポインタを渡す。戻ったとき、jfloat が設定されている。 |
局所変数の取得 - 倍精度浮動小数点数型
jvmtiError
GetLocalDouble(jvmtiEnv* env,
jthread thread,
jint depth,
jint slot,
jdouble* value_ptr)
この関数を使うと、型が long である局所変数の値を取得できます。
|
名前
|
型
|
説明
|
thread | jthread |
変数の値を含むフレームのスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
depth | jint |
変数の値を含むフレームの深さ。
|
slot | jint |
変数のスロット番号。
|
value_ptr | jdouble* |
戻ったとき、変数の値をポイントする。
エージェントは jdouble にポインタを渡す。戻ったとき、jdouble が設定されている。 |
局所変数の設定 - オブジェクト型
jvmtiError
SetLocalObject(jvmtiEnv* env,
jthread thread,
jint depth,
jint slot,
jobject value)
この関数を使うと、型が Object または Object のサブクラスである局所変数の値を設定できます。
|
名前
|
型
|
説明
|
thread | jthread |
変数の値を含むフレームのスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
depth | jint |
変数の値を含むフレームの深さ。
|
slot | jint |
変数のスロット番号。
|
value | jobject |
変数の新しい値。
|
局所変数の設定 - 整数型
jvmtiError
SetLocalInt(jvmtiEnv* env,
jthread thread,
jint depth,
jint slot,
jint value)
この関数を使うと、型が int、short、char、byte、boolean のいずれかである局所変数の値を設定できます。
|
名前
|
型
|
説明
|
thread | jthread |
変数の値を含むフレームのスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
depth | jint |
変数の値を含むフレームの深さ。
|
slot | jint |
変数のスロット番号。
|
value | jint |
変数の新しい値。
|
局所変数の設定 - 長整数型
jvmtiError
SetLocalLong(jvmtiEnv* env,
jthread thread,
jint depth,
jint slot,
jlong value)
この関数を使うと、型が long である局所変数の値を設定できます。
|
名前
|
型
|
説明
|
thread | jthread |
変数の値を含むフレームのスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
depth | jint |
変数の値を含むフレームの深さ。
|
slot | jint |
変数のスロット番号。
|
value | jlong |
変数の新しい値。
|
局所変数の設定 - 浮動小数点数型
jvmtiError
SetLocalFloat(jvmtiEnv* env,
jthread thread,
jint depth,
jint slot,
jfloat value)
この関数を使うと、型が float である局所変数の値を設定できます。
|
名前
|
型
|
説明
|
thread | jthread |
変数の値を含むフレームのスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
depth | jint |
変数の値を含むフレームの深さ。
|
slot | jint |
変数のスロット番号。
|
value | jfloat |
変数の新しい値。
|
局所変数の設定 - 倍精度浮動小数点数型
jvmtiError
SetLocalDouble(jvmtiEnv* env,
jthread thread,
jint depth,
jint slot,
jdouble value)
この関数を使うと、型が double である局所変数の値を設定できます。
|
名前
|
型
|
説明
|
thread | jthread |
変数の値を含むフレームのスレッド。
thread が NULL の場合、現在のスレッドが使用される。
|
depth | jint |
変数の値を含むフレームの深さ。
|
slot | jint |
変数のスロット番号。
|
value | jdouble |
変数の新しい値。
|
ブレークポイント
ブレークポイント関数:
ブレークポイントの設定
jvmtiError
SetBreakpoint(jvmtiEnv* env,
jmethodID method,
jlocation location)
method および location で指定された命令にブレークポイントを設定します。1 つの命令に対して設定できるブレークポイントは 1 つだけです。
指定した命令が実行される直前に、Breakpoint イベントが生成されます。
ブレークポイントの解除
jvmtiError
ClearBreakpoint(jvmtiEnv* env,
jmethodID method,
jlocation location)
method および location で指定されたバイトコードに設定されているブレークポイントを解除します。
監視されるフィールド
監視されるフィールド関数:
フィールドアクセスの監視の設定
jvmtiError
SetFieldAccessWatch(jvmtiEnv* env,
jclass klass,
jfieldID field)
klass および field で指定されたフィールドがアクセスされようとした時点で、FieldAccess イベントを生成します。イベントは、ClearFieldAccessWatch を使って取り消されるまで、フィールドがアクセスされるたびに生成されます。Java プログラミング言語コードまたは JNI コードからのフィールドアクセスが監視され、ほかの手段で変更されるフィールドは監視されません。JVM TI のユーザーは、自分自身のフィールドアクセスによって監視イベントがトリガーされることに注意してください。1 つのフィールドに対し、フィールドアクセスの監視を 1 つだけ設定できます。フィールドの変更はアクセスとはみなされません。変更を監視するには、SetFieldModificationWatch を使います。
フィールドアクセスの監視の解除
jvmtiError
ClearFieldAccessWatch(jvmtiEnv* env,
jclass klass,
jfieldID field)
SetFieldAccessWatch を使って以前に設定した、klass および field で指定されるフィールドに対するフィールドアクセスの監視を取り消します。
フィールド変更の監視の設定
jvmtiError
SetFieldModificationWatch(jvmtiEnv* env,
jclass klass,
jfieldID field)
klass および field で指定されたフィールドが変更されようとした時点で、FieldModification イベントを生成します。イベントは、ClearFieldModificationWatch を使って取り消されるまで、フィールドが変更されるたびに生成されます。Java プログラミング言語コードまたは JNI コードからのフィールド変更が監視され、ほかの手段で変更されるフィールドは監視されません。JVM TI のユーザーは、自分自身で実行するフィールド変更によって監視イベントがトリガーされることに注意してください。1 つのフィールドに対し、フィールド変更の監視を 1 つだけ設定できます。
フィールド変更の監視の解除
jvmtiError
ClearFieldModificationWatch(jvmtiEnv* env,
jclass klass,
jfieldID field)
klass および field で指定されるフィールドに対して、SetFieldModificationWatch を使って以前に設定したフィールド変更の監視を取り消します。
クラス
クラス関数:
クラスの型:
クラスのフラグおよび定数:
ロード済みクラスの取得
jvmtiError
GetLoadedClasses(jvmtiEnv* env,
jint* class_count_ptr,
jclass** classes_ptr)
仮想マシンにロードされている全クラスの配列を返します。配列内のク ラスの数は class_count_ptr、配列自体は classes_ptr によって返されます。
返されるリストには、すべての型の配列クラス (プリミティブ型の配列を含む) が含まれます。プリミティブクラス (たとえば、java.lang.Integer.TYPE) は、このリストには含まれません。
|
名前
|
型
|
説明
|
class_count_ptr | jint* |
戻ったとき、クラスの数をポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
classes_ptr | jclass** |
戻ったとき、各クラスへの参照 (クラスごとに 1 つずつ) の配列をポイントする。
エージェントは jclass* にポインタを渡す。戻ったとき、jclass* は、サイズ *class_count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。classes_ptr から返されるオブジェクトは JNI ローカル参照であり、管理する必要がある。
|
クラスローダークラスの取得
jvmtiError
GetClassLoaderClasses(jvmtiEnv* env,
jobject initiating_loader,
jint* class_count_ptr,
jclass** classes_ptr)
このクラスローダーが起動ローダーとして記録されているクラスの配列を返します。返される配列内の各クラスは、このクラスローダーによって直接定義されて作成されたものか、または別のクラスローダーに委譲して作成されたものです。『Java 仮想マシン仕様』の「Creation and Loading」セクションを参照してください。
JDK 1.1 の実装では、起動クラスローダーと定義クラスローダーの区別が認識されないため、この関数は、仮想マシンにロードされたすべてのクラスを返します。配列内のク ラスの数は class_count_ptr、配列自体は classes_ptr によって返されます。
|
名前
|
型
|
説明
|
initiating_loader | jobject
|
起動クラスローダー。
initiating_loader が NULL の場合、ブートストラップローダーによって起動されたクラスが返される。
|
class_count_ptr | jint* |
戻ったとき、クラスの数をポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
classes_ptr | jclass** |
戻ったとき、各クラスへの参照 (クラスごとに 1 つずつ) の配列をポイントする。
エージェントは jclass* にポインタを渡す。戻ったとき、jclass* は、サイズ *class_count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。classes_ptr から返されるオブジェクトは JNI ローカル参照であり、管理する必要がある。
|
クラスのシグニチャーの取得
jvmtiError
GetClassSignature(jvmtiEnv* env,
jclass klass,
char** signature_ptr,
char** generic_ptr)
klass で指定されたクラスに、JNI 型のシグニチャーとクラスの総称シグニチャーを返します。たとえば、java.util.List が "Ljava/util/List;" で、int[] が "[I" の場合、返されるプリミティブクラスの名前は、対応するプリミティブ型の型シグニチャー文字になります。たとえば、java.lang.Integer.TYPE は "I" です。
|
名前
|
型
|
説明
|
klass | jclass |
照会するクラス。
|
signature_ptr | char
** |
戻ったとき、クラスの JNI 型シグニチャー (修正 UTF-8 文字列としてエンコードされる) をポイントする。
エージェントは char* にポインタを渡す。char* は、新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。signature_ptr が NULL の場合、シグニチャーは返されない。
|
generic_ptr | char
** |
戻ったとき、クラスの総称シグニチャー (修正 UTF-8 文字列としてエンコードされる) をポイントする。クラスの総称シグニチャー属性が存在しない場合は、戻ったとき NULL をポイントする。
エージェントは char* にポインタを渡す。char* は、新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。generic_ptr が NULL の場合、総称シグニチャーは返されない。
|
クラスのステータスの取得
jvmtiError
GetClassStatus(jvmtiEnv* env,
jclass klass,
jint* status_ptr)
クラスのステータスを取得します。次のビットのうち、0 個以上のビットがセットされます。
|
定数
|
値
|
説明
|
JVMTI_CLASS_STATUS_VERIFIED | 1 |
クラスのバイトコードが検証された。
|
JVMTI_CLASS_STATUS_PREPARED | 2 |
クラスの準備が完了した。
|
JVMTI_CLASS_STATUS_INITIALIZED | 4 |
クラスの初期化が完了した。静的な初期化子が実行された。
|
JVMTI_CLASS_STATUS_ERROR | 8 |
初期化中のエラーによりクラスが使用できない。
|
JVMTI_CLASS_STATUS_ARRAY | 16 |
クラスは配列。設定されている場合、その他のすべてのビットはゼロ。
|
JVMTI_CLASS_STATUS_PRIMITIVE | 32 |
クラスはプリミティブクラス (java.lang.Integer.TYPE など)。設定されている場合、その他のすべてのビットはゼロ。
|
|
名前
|
型
|
説明
|
klass | jclass |
照会するクラス。
|
status_ptr | jint* |
戻ったとき、このクラスの現在の状態としてクラスのステータスフラグを 1 つ以上ポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
ソースファイル名の取得
jvmtiError
GetSourceFileName(jvmtiEnv* env,
jclass klass,
char** source_name_ptr)
klass で指定されたクラスについて、source_name_ptr を介してソースファイル名を返します。返される文字列は、ファイル名だけで、ディレクトリ名は含まれません。
プリミティブクラス (たとえば、java.lang.Integer.TYPE) および配列の場合、この関数は JVMTI_ERROR_ABSENT_INFORMATION を返します。
|
名前
|
型
|
説明
|
klass | jclass |
照会するクラス。
|
source_name_ptr | char** |
戻ったとき、クラスのソースファイル名 (修正 UTF-8 文字列としてエンコードされる) をポイントする。
エージェントは char* にポインタを渡す。char* は、新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。 |
クラスの修飾子の取得
jvmtiError
GetClassModifiers(jvmtiEnv* env,
jclass klass,
jint* modifiers_ptr)
klass で指定されたクラスのアクセスフラグを、modifiers_ptr を介して返します。アクセスフラグについては、『Java 仮想マシン仕様』の「Class File Format」の章で定義されています。
クラスが配列クラスの場合、その public、private および protected 修飾子は、そのコンポーネント型の修飾子と同じです。プリミティブ型の配列の場合、このコンポーネント型は、プリミティブクラスの 1 つ (たとえば、java.lang.Integer.TYPE) で表現されます。
クラスがプリミティブクラスの場合、その public 修飾子は常に true になります。また、その protected 修飾子および private 修飾子は常に false になります。
クラスが配列クラスまたはプリミティブクラスの場合、その final 修飾子は常に true になり、interface 修飾子は常に false になります。その他の修飾子の値は、この仕様では判定されません。
|
名前
|
型
|
説明
|
klass | jclass |
照会するクラス。
|
modifiers_ptr | jint* |
戻ったとき、このクラスの現在のアクセスフラグをポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
クラスのメソッドの取得
jvmtiError
GetClassMethods(jvmtiEnv* env,
jclass klass,
jint* method_count_ptr,
jmethodID** methods_ptr)
klass で指定されたクラスに含まれるメソッドの数を method_count_ptr を介して返し、メソッド ID のリストを methods_ptr を介して返します。メソッドのリストには、本来のメソッドだけでなく、コンストラクタおよび static 初期化子も含まれます。直接宣言されたメソッドだけが返されます (継承したメソッドは返されない)。配列クラスおよびプリミティブクラス (たとえば、java.lang.Integer.TYPE) の場合、空のメソッドリストが返されます。
|
名前
|
型
|
説明
|
klass | jclass |
照会するクラス。
|
method_count_ptr | jint* |
戻ったとき、このクラスで宣言されているメソッドの数をポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
methods_ptr | jmethodID** |
戻ったとき、メソッド ID の配列をポイントする。
エージェントは jmethodID* にポインタを渡す。戻ったとき、jmethodID* は、サイズ *method_count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。 |
クラスのフィールドの取得
jvmtiError
GetClassFields(jvmtiEnv* env,
jclass klass,
jint* field_count_ptr,
jfieldID** fields_ptr)
klass で指定されたクラスに含まれるフィールドの数を field_count_ptr を介して返し、フィールド ID のリストを fields_ptr を介して返します。直接宣言されたフィールドだけが返されます (継承したフィールドは返されない)。フィールドは、クラスファイル内に出現する順序で返されます。配列クラスおよびプリミティブクラス (たとえば、java.lang.Integer.TYPE) の場合、空のフィールドリストが返されます。JNI を使って、配列の長さを判別してください。
|
名前
|
型
|
説明
|
klass | jclass |
照会するクラス。
|
field_count_ptr | jint* |
戻ったとき、このクラスで宣言されているフィールドの数をポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
fields_ptr | jfieldID** |
戻ったとき、フィールド ID の配列をポイントする。
エージェントは jfieldID* にポインタを渡す。戻ったとき、jfieldID* は、サイズ *field_count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。 |
実装されたインタフェースの取得
jvmtiError
GetImplementedInterfaces(jvmtiEnv* env,
jclass klass,
jint* interface_count_ptr,
jclass** interfaces_ptr)
このクラスの直接のスーパーインタフェースを返します。クラスに対しては、この関数は、implements 節で宣言されているインタフェースを返します。インタフェースに対しては、この関数は、extends 節で宣言されているインタフェースを返します。配列クラスおよびプリミティブクラス (たとえば、java.lang.Integer.TYPE) の場合、空のインタフェースリストが返されます。
|
名前
|
型
|
説明
|
klass | jclass |
照会するクラス。
|
interface_count_ptr | jint* |
戻ったとき、インタフェースの数をポイントする。
エージェントは jint にポインタを渡す。戻ったとき、jint が設定されている。 |
interfaces_ptr | jclass** |
戻ったとき、インタフェースの配列をポイントする。
エージェントは jclass* にポインタを渡す。戻ったとき、jclass* は、サイズ *interface_count_ptr の新しく割り当てられた配列をポイントする。この配列は、Deallocate を使って解放する必要がある。interfaces_ptr から返されるオブジェクトは JNI ローカル参照であり、管理する必要がある。
|
クラスバージョン番号の取得
jvmtiError
GetClassVersionNumbers(jvmtiEnv* env,
jclass klass,
jint* minor_version_ptr,
jint* major_version_ptr)
klass に指定されたクラスについては、『Java 仮想マシン仕様』の「Class File Format」の章で定義されているように、マイナーバージョン番号とメジャーバージョン番号を返します。