JVM Tool Interfaceとは
JVMTM Tool Interface (JVM TI)は、開発ツールや監視ツールで使用されるプログラミング・インタフェースです。 JavaTM仮想マシン(VM)で動作するアプリケーションの状態検査と実行制御の両方の機能を提供します。
JVM TIは、プロファイリング・ツール、デバッグ・ツール、監視ツール、スレッド分析ツール、カバレッジ分析ツールなど、VMの状態その他にアクセスする必要がある各種ツールのVMインタフェースとして機能します。
JVM TIは、JavaTM仮想マシンのすべての実装で使用できるとはかぎりません。
JVM TIは双方向のインタフェースです。 JVM TIのクライアント(以下エージェントと呼ぶ)は、興味のある事象についてイベント経由で通知を受け取ることができます。 JVM TIは、多数の関数を介して、アプリケーションのクエリーや制御を(イベントへの応答として、あるいはイベントから独立して)行えます。
個々のエージェントは同一のプロセスで実行され、検査対象のアプリケーションを実行する仮想マシンと直接通信します。 この通信には、ネイティブ・インタフェース(JVM TI)が使用されます。 ネイティブのインプロセス・インタフェースにより、ツール側への侵入は最小限に抑えながら、最大限の制御が可能になります。 通常、エージェントは比較的コンパクトです。 エージェントは、ターゲット・アプリケーションの通常の実行を妨げることなく、ツールの機能の大部分を実装する別のプロセスによって制御できます。
アーキテクチャ
ツールへの書込みは、JVM TIを使って直接行われるか、高度インタフェースを使って間接的に行われます。 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)になります。 LinuxTMオペレーティング環境では、エージェント・ライブラリは共有オブジェクト(.so
ファイル)です。
VM起動時にエージェントを起動するには、コマンド行オプションを使ってエージェント・ライブラリの名前を指定します。 実装によっては、ライブ段階でエージェントを起動するメカニズムをサポートしている可能性があります。 その起動方法の詳細は、実装に固有となります。
静的リンク・エージェント(導入されたバージョン: 1.2.3)
ネイティブJVMTIエージェントは、VMと静的にリンクできます。 ライブラリ・イメージとVMイメージとの結合方法は、実装に依存します。 イメージがVMと結合されたエージェントLが静的リンクとして定義されるのは、そのエージェントがAgent_OnLoad_Lという名前の関数をエクスポートする場合のみです。
静的リンク・エージェントLからAgent_OnLoad_Lという名前の関数とAgent_OnLoadという名前の関数がエクスポートされた場合、Agent_OnLoad関数は無視されます。 エージェントLが静的リンクの場合、Agent_OnLoad関数で規定されたのと同じ引数と期待される戻り値を指定して、Agent_OnLoad_L関数が呼び出されます。 静的リンクのエージェントLは、同名のエージェントが動的にロードされるのを禁止します。
VMは、その実行中に動的エントリ・ポイントAgent_OnUnLoadが呼び出されていたのと同じポイントで、エージェントのAgent_OnUnload_L関数を呼び出します(そのような関数がエクスポートされていた場合)。 静的にロードされたエージェントはアンロードできません。 それでも、エージェントのシャットダウンに関する他のなんらかのタスクを行えるように、Agent_OnUnload_L関数が呼び出されます。 静的リンク・エージェントLからAgent_OnUnLoad_Lという名前の関数とAgent_OnUnLoadという名前の関数がエクスポートされた場合、Agent_OnUnLoad関数は無視されます。
エージェントLが静的リンクの場合、Agent_OnAttach関数で規定されたのと同じ引数と期待される戻り値を指定して、Agent_OnAttach_L関数が呼び出されます。 静的リンク・エージェントLからAgent_OnAttach_Lという名前の関数とAgent_OnAttachという名前の関数がエクスポートされた場合、Agent_OnAttach関数は無視されます。
エージェントのコマンド行オプション
以下の「コマンド行オプション」という語は、JNI呼び出しAPIのJNI_CreateJavaVM
関数において、JavaVMInitArgs
引数で指定されるオプションを意味します。
エージェントを適切にロードして実行するには、VMの起動時に次の2つのうちいずれかのコマンド行オプションが必要です。 これらの引数は、エージェントを含むライブラリと、起動時に渡されるオプションの文字列を指定します。
-
-agentlib:
<agent-lib-name>=
<options>
-
-agentlib:
の後の名前は、ロードするライブラリの名前です。 ライブラリの検索(その完全名と場所の両方)は、プラットフォーム固有の方法で進行します。 通常、<agent-lib-name>はオペレーティング・システム固有のファイル名に展開されます。 <options>は、起動時にエージェントに渡されます。 たとえば、オプション-agentlib:foo=opt1,opt2
が指定されている場合、VMは、WindowsTMの下のシステムPATH
から共有ライブラリfoo.dll
、またはLinuxTMの下のLD_LIBRARY_PATH
からlibfoo.so
をロードしようとします。 エージェントのライブラリが実行可能ファイルに静的にリンクされている場合、実際のロード・タスクは発生しません。
-
-agentpath:
<path-to-agent>=
<options>
-
-agentpath:
の後ろには、ライブラリをロードする絶対パスを指定します。 ライブラリ名の展開は行われません。 <options>は、起動時にエージェントに渡されます。 たとえば、オプション-agentpath:c:\myLibs\foo.dll=opt1,opt2
が指定された場合、VMは、共有ライブラリc:\myLibs\foo.dll
をロードしようとします。 エージェントのライブラリが実行可能ファイルに静的にリンクされている場合、実際のロード・タスクは発生しません。
動的共有ライブラリ・エージェントの場合、ライブラリ内の起動ルーチンAgent_OnLoad
が呼び出されます。 エージェントのライブラリが実行可能ファイルに静的にリンクされている場合、システムはAgent_OnLoad_<agent-lib-name>
エントリ・ポイント(<agent-lib-name>はエージェントのベース名)を呼び出そうとします。 上の例(-agentpath:c:\myLibs\foo.dll=opt1,opt2
)の場合、システムはAgent_OnLoad_foo
起動ルーチンを見つけて呼び出そうとします。
バイト・コード・インストゥルメンテーション(bytecode instrumentation)のために必要な場合、ツール内でJavaプログラミング言語コードを使用しやすくするため、-agentlib:
または-agentpath:
を指定してロードされたライブラリから、JNIネイティブ・メソッド実装が検索されます。
エージェント・ライブラリは、その他のすべてのライブラリが検索されたあと検索されます。非エージェント・メソッドのネイティブ・メソッド実装を上書きまたは遮断するエージェントは、NativeMethodBindイベントを使用できます。
これらのスイッチは上記の処理のみを行います。VMやJVM TIの状態を変更することはありません。 JVM TIやJVM TIの側面を有効にするためにコマンド行オプションを指定する必要はありません。これは、プログラム内で権限を使用して処理されます。
エージェントの起動
VMは、起動関数を呼び出すことで各エージェントを起動します。 OnLoad
段階でエージェントを起動する場合は、関数Agent_OnLoad
(静的リンク・エージェントの場合はAgent_OnLoad_L
)が呼び出されます。 ライブ段階でエージェントを起動する場合は、関数Agent_OnAttach
(静的リンク・エージェントの場合はAgent_OnAttach_L
)が呼び出されます。 起動関数の呼出しは、エージェントごとに1回だけ行われます。
エージェントの起動(OnLoad段階)
OnLoad
段階でエージェントを起動する場合、そのエージェント・ライブラリは次のプロトタイプを持つ起動関数をエクスポートする必要があります。
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
「L」という名前の静的リンク・エージェントの場合:
JNIEXPORT jint JNICALL
Agent_OnLoad_L(JavaVM *vm, char *options, void *reserved)
VMは、この関数を呼び出すことでエージェントを起動します。 この呼出しはVM初期化の早い段階で行われるため、次のことが言えます。
-
システム・プロパティは、VMの起動で使用される前に設定できる
-
すべての権限を使用できる(ただし、VMを構成する権限はこのときしか使用できない。詳細は「権限関数」セクションを参照)
- バイト・コードが実行されていない
- クラスがロードされていない
- オブジェクトが作成されていない
VMは、Agent_OnLoad
またはAgent_OnLoad_<agent-lib-name>
関数を、第2引数に<options>を指定して呼び出します。つまり、コマンド行オプションの例で言えば、Agent_OnLoad
のchar *options
引数に"opt1,opt2"
が渡されます。 options
引数は修正UTF-8文字列としてエンコードされます。 =<options>が指定されなかった場合は、長さゼロの文字列がoptions
に渡されます。 options
文字列の存続期間は、Agent_OnLoad
またはAgent_OnLoad_<agent-lib-name>
呼出しの間です。 この期間を超えて必要な場合は、文字列または文字列の一部をコピーする必要があります。 Agent_OnLoad
が呼び出されてから復帰するまでの期間は、OnLoad段階と呼ばれます。 OnLoad 段階ではVMは初期化されていないため、Agent_OnLoad
の内側で使用できる操作セットは限定されます(この時点で使用可能な機能については関数の説明を参照)。 エージェントが安全に実行できるのは、オプションの処理や、SetEventCallbacks
でイベント・コールバックを設定する処理です。 エージェントはVM初期化イベントを受け取った後(つまり、VMInitコールバックが呼び出された後)、初期化を完了させることができます。
原理の説明: 早い段階での起動が必要なのは、エージェントが目的の権限(その多くはVMの初期化前に設定する必要がある)を設定できるようにするためです。 JVMDIでは-Xdebugコマンド行オプションによって、非常に粗粒度の権限制御機能が提供されていました。 JVMPI実装では、様々なテクニックを使用して単一の「JVMPIオン」スイッチが提供されます。 必要な権限とパフォーマンスへの影響のバランスを取るために必要な、細粒度の制御機能を提供できる適度なコマンド行オプションはありません。 また、早い段階での起動は、エージェントが実行環境を制御できるようにする(ファイル・システムやシステム・プロパティを変更して機能をインストールできるようにする)ためにも必要です。
Agent_OnLoad
またはAgent_OnLoad_<agent-lib-name>
の戻り値は、エラーを示すために使用されます。 ゼロ以外の値はすべてエラーを示しており、エラーが発生するとVMは終了します。
エージェントの起動(ライブ段階)
VMによっては、そのVM内でライブ段階でエージェントを起動するメカニズムをサポートしている可能性があります。 そのサポート方法の詳細は、実装に固有となります。 たとえば、あるツールでは、何らかのプラットフォーム固有のメカニズムや実装固有のAPIを使用することで、実行中のVMに接続して特定のエージェントの起動を要求する可能性があります。
ライブ段階でエージェントを起動する場合、そのエージェント・ライブラリは次のプロトタイプを持つ起動関数をエクスポートする必要があります。
JNIEXPORT jint JNICALL
Agent_OnAttach(JavaVM* vm, char *options, void *reserved)
「L」という名前の静的リンク・エージェントの場合:
JNIEXPORT jint JNICALL
Agent_OnAttach_L(JavaVM* vm, char *options, void *reserved)
VMは、この関数を呼び出すことでエージェントを起動します。 これは、VMに接続されたスレッドのコンテキスト内で呼び出されます。 第1引数の<vm>は、Java VMです。 <options>引数はエージェントに提供される起動オプションです。<options>は修正UTF-8 文字列としてエンコードされます。 起動オプションが指定されなかった場合は、長さゼロの文字列がoptions
に渡されます。 options
文字列の存続期間は、Agent_OnAttach
またはAgent_OnAttach_<agent-lib-name>
呼出しの間です。 この期間を超えて必要な場合は、文字列または文字列の一部をコピーする必要があります。
ライブ段階では権限の一部が使用できない可能性があります。
Agent_OnAttach
またはAgent_OnAttach_<agent-lib-name>
関数は、エージェントを初期化し、エラーが発生したかどうかを示す値をVMに返します。 ゼロ以外の値はすべて、エラーを表します。 エラーが発生してもVMは終了しません。 代わりにVMは、そのエラーを無視するか、そのエラーを標準エラーに出力したりシステム・ログに記録したりするなど、何らかの実装固有のアクションを実行します。
エージェントの停止
ライブラリは、オプションで、次のプロトタイプを持つ停止関数をエクスポートできます。
JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm)
「L」という名前の静的リンク・エージェントの場合:
JNIEXPORT void JNICALL
Agent_OnUnload_L(JavaVM *vm)
この関数は、ライブラリのアンロードの直前にVMによって呼び出されます。 ライブラリは(実行可能ファイルに静的にリンクされたライブラリでないかぎり)アンロードされます。この関数が呼び出されるのは、なんらかのプラットフォーム固有のメカニズムによってアンロードが発生した場合(このドキュメントではアンロード・メカニズムについては規定していない)、あるいはVMの終了(正常終了または起動エラーなどのVMエラーによるもの)によってライブラリが(実質的に)アンロードされる場合です。 未集計停止は当然、このルールの例外です。 この関数とVM終了イベントの違いに注意してください。VM終了イベントが送信されるためには、VMが少なくとも初期化のポイントまで実行済であり、かつVMDeathのコールバックを設定し、このイベントを有効化した有効なJVM TI環境が存在している必要があります。 Agent_OnUnload
またはAgent_OnUnload_<agent-lib-name>
ではこれらの条件は一切不要です。また、その他の理由でライブラリがアンロードされる場合もこの関数が呼び出されます。 VM終了イベントが送信される場合、それは、この関数が呼び出される前に送信されます(VMの終了によってこの関数が呼び出されると仮定した場合)。 この関数を使えば、エージェントによって割り当てられたリソースをクリーンアップできます。
埋め込みVMや単にスクリプト内の深い場所で起動されるVMなどでは、コマンド行のアクセスや変更が常に可能であるとはかぎらないため、JAVA_TOOL_OPTIONS
変数が用意されています。これを使えば、そうした場合でもエージェントを起動できます。
環境変数などの名前付き文字列をサポートするプラットフォームでは、JAVA_TOOL_OPTIONS
変数がサポートされている可能性があります。 この変数は、空白文字の境界で複数のオプションに分解されます。 空白文字には、空白、タブ、復帰、復帰改行、垂直タブ、用紙送りなどがあります。 一連の空白文字は単一の空白文字と同等とみなされます。 空白文字は、引用符で囲まれていないかぎり、オプションには含められません。 引用方法は次のとおりです。
- 一重引用符の組('')に囲まれた、一重引用符を除くすべての文字は引用として囲まれる。
- 一重引用符の組の内部にある二重引用符には、特殊な意味はない。
- 二重引用符の組("")に囲まれた、二重引用符を除くすべての文字は引用として囲まれる。
- 二重引用符の組の内部にある一重引用符には、特殊な意味はない。
- 変数内の任意の場所を引用符で囲むことができる。
- 引用符で囲まれた空白文字には、特殊な意味はない。その他の文字と同様にオプションに含めることができ、区切り文字として機能しない。
- 引用符の組自体はオプションに含まれない。
JNI_CreateJavaVM
(JNI呼出しAPI内)は、JavaVMInitArgs
引数に指定されたオプションの先頭に、これらのオプションを付加します。 セキュリティに問題がある場合、プラットフォームはこの機能を無効化することがあります。たとえばリファレンス実装は、UNIXシステムで実効ユーザーIDまたはグループIDが実際のIDと異なる場合に、この機能を無効化します。 この機能はツールの初期化(具体的にはネイティブまたはJavaプログラミング言語エージェントの起動など)をサポートするためのものです。 複数のツールがこの機能の使用を要求する可能性があるため、変数を上書きするのではなく、かわりに変数にオプションを追加すべきです。 変数が処理されるのは、JNI呼出しAPIのVM作成呼出し時であるため、ランチャによって処理されるオプション(VM選択オプションなど)は処理されません。
環境
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仮想マシン・バイトコード命令を変更する機能)のサポートが提供されます。 これらの変更の目的は通常、メソッドのコードに「イベント」を追加すること(たとえば、メソッドの先頭にMyProfiler.methodEntered()
呼出しを追加すること)です。 変更は単に追加されるため、アプリケーションの状態や動作が変更されることはありません。 挿入されるエージェント・コードは標準のバイトコードなので、VMをフル・スピードで実行できます(ターゲット・プログラムのみでなくインストゥルメンテーションも最適化される)。 インストゥルメンテーションにバイトコード実行からの切替えが含まれていなければ、高コストの状態遷移が不要となります。 その結果、イベントのパフォーマンスが高くなります。 さらにこのアプローチは、完全な制御機能をエージェントに提供します。コードの「関心のある」部分(エンド・ユーザーのコードなど)にインストゥルメンテーションを限定可能で、しかも条件付きにできます。 インストゥルメンテーションは、全体をJavaプログラミング言語コード内で実行することも、ネイティブ・エージェント内への呼出しを行うこともできます。 インストゥルメンテーションは、単純にカウンタを保持することも、イベントの統計サンプリングを行うこともできます。
インストゥルメンテーションの挿入は、次の3とおりのうちのいずれかの方法で行います。
-
静的インストゥルメンテーション: クラス・ファイルは、たとえばインストゥルメンテーションを追加する目的で変更された
*.class
ファイルを含む複製ディレクトリを作成するなどの方法で、VMにロードされる前に計測されます。 この方法はきわめて不自然であり、一般に、ロードされるクラス・ファイルの出所をエージェント側で知ることはできません。
-
ロード時のインストゥルメンテーション: クラス・ファイルがVMにロードされるとき、クラス・ファイルのrawバイトは、インストゥルメンテーション用としてエージェントに送信されます。 クラスのロードによって発生した
ClassFileLoadHook
イベントが、この機能を提供します。 このメカニズムは効率がよく、1回かぎりのインストゥルメンテーションに完全にアクセスできます。
-
動的インストゥルメンテーション: すでにロード済であり、場合によっては実行されている可能性もあるクラスが、変更されます。 このオプション機能は、
RetransformClasses
関数を呼び出すことでトリガーされるClassFileLoadHook
イベントによって提供されます。 クラスは複数回変更できるほか、元の状態に戻すこともできます。 このメカニズムを使えば、実行中に変化するインストゥルメンテーションを実現できます。
このインタフェースに用意されたクラス変更機能は、インストゥルメンテーションのメカニズムを提供し(ClassFileLoadHook
イベントとRetransformClasses
関数)、開発時には修正しながらデバッグを続けていく(RedefineClasses
関数)ために用意されています。
依存関係が混乱しないように、特にコア・クラスを計測する場合は、注意が必要です。 たとえば、各オブジェクト割当ての通知を受けるアプローチでは、Object
でコンストラクタを計測します。 コンストラクタが最初は空であるとすると、このコンストラクタを次のように変更します。
public Object() {
MyProfiler.allocationTracker(this);
}
ただし、ClassFileLoadHook
イベントを使用してこの変更を行った場合、その影響が次のように典型的なVMに及ぶ可能性があります。最初に作成されるオブジェクトがコンストラクタを呼び出し、その結果、MyProfiler
のクラス・ロードが開始されます。次にオブジェクトが作成されますが、MyProfiler
はまだロードされていないので無限再帰に陥り、スタック・オーバーフローが発生します。 これを改良するには、安全な時間になるまで追跡メソッドの呼出しを遅らせます。 たとえば、VMInit
イベントのハンドラ内でtrackAllocations
を設定できます。
static boolean trackAllocations = false;
public Object() {
if (trackAllocations) {
MyProfiler.allocationTracker(this);
}
}
SetNativeMethodPrefix
を使えば、ラッパー・メソッドによるネイティブ・メソッドの計測が可能となります。
バイトコード・モジュール内のコードのインストゥルメンテーション
エージェントは、モジュールAddModuleReads
、AddModuleExports
、AddModuleOpens
、AddModuleUses
、AddModuleProvides
を使用して、モジュールを更新して、読み込んだモジュールのセット、他のモジュールにエクスポートまたは開くパッケージのセット、または使用して提供するサービスを展開できます。
ブートストラップ・クラス・ローダーの検索パスまたはメイン・クラスをロードするクラス・ローダーの検索パスにサポート・クラスをデプロイするエージェントの助けとして、Java仮想マシンはClassFileLoadHook
イベントによって変換されたクラスのモジュールを読み込むように調整します両方のクラス・ローダーの名前のないモジュール。
修正UTF-8の文字列エンコーディング
JVM TIは、修正UTF-8を使って文字列をエンコードします。 これは、JNIが使用するのと同じエンコーディングです。 修正UTF-8と標準のUTF-8との違いは、補助文字とnull文字の表現方法にあります。 詳細については、JNI仕様の「変更後のUTF-8文字列」セクションを参照してください。
仕様のコンテキスト
このインタフェースはJava仮想マシンで実行されるアプリケーションの状態にアクセスするため、用語はJavaプラットフォームに関するものであり、特に言及している場合を除いてネイティブ・プラット・フォームに関するものではありません。 例を示します。
- 「スレッド」はJavaプログラミング言語のスレッドを意味する。
- 「スタック・フレーム」はJava仮想マシンのスタック・フレームを意味する。
- 「クラス」はJavaプログラミング言語のクラスを意味する。
- 「ヒープ」はJava仮想マシンのヒープを意味する。
- 「モニター」はJavaプログラミング言語のオブジェクト・モニターを意味する。
Sun、Sun Microsystems、Sun のロゴ、Java、および JVM は、米国ならびにその他の国における Oracle Corporation およびその関連会社の登録商標です。
関数
関数のアクセス
ネイティブ・コードは、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
のversion
引数は、JVM TIのバージョンでなければいけません。 返された環境のバージョンが要求されたバージョンと異なることもありますが、返された環境は互換性があるはずです。 GetEnv
からJNI_EVERSION
が返されるのは、互換性のあるバージョンが使用可能でない場合、JVM TIがサポートされていない場合、または現在のVM構成でJVM TIがサポートされていない場合です。 特定のコンテキストでJVM TI環境を作成するためのその他のインタフェースが追加される可能性があります。 各環境はそれぞれ独自の状態(必要なイベント、イベント処理関数、権限など)を持ちます。 環境を解放するにはDisposeEnvironment
を使用します。 したがって、スレッドごとに1つの環境が用意される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例外に関するセクションを参照してください。
関数の索引
メモリー管理
メモリー管理関数:
これらの関数は、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
形式の状態に変換するために使用します。
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は、予約ビットをゼロに設定する必要があります。 エージェントは予約ビットを無視すべきです。予約ビットは、ゼロであると仮定すべきではなく、したがって比較式に含めるべきではありません。
例
これから説明する値は、予約ビットとベンダー・ビットを除外しています。
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";
}
ライブ段階でしか呼び出せない
いいえ
17
1.0
パラメータ
名前 | 型 | 説明 |
thread | jthread |
照会するスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
thread_state_ptr | jint* |
戻ったとき、スレッド状態フラグの定義に従って状態フラグをポイントする。
エージェントはjint へのポインタを渡す。 戻ったとき、jint が設定されている。 |
現在のスレッドの取得
jvmtiError
GetCurrentThread(jvmtiEnv* env,
jthread* thread_ptr)
現在のスレッドを取得します。 現在のスレッドとは、この関数を呼び出したJavaプログラミング言語スレッドのことです。 can_generate_early_vmstart
機能が有効で、java.lang.Thread
クラスがまだ初期化されていない場合、関数は開始フェーズでNULL
を返します。
スレッドを引数に取るJVM TI関数のほとんどは、NULL
を現在のスレッドを意味するものとして受け入れます。
開始またはライブ段階でしか呼び出せない
いいえ
18
1.1
パラメータ
名前 | 型 | 説明 |
thread_ptr | jthread* |
戻り時には、現在のスレッド、またはNULL をポイントします。
エージェントは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
配列内に返されます。 現在中断しているスレッドの状態は変わりません。
ライブ段階でしか呼び出せない
いいえ
92
1.0
パラメータ
名前 | 型 | 説明 |
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()
によって中断されているスレッドの実行を再開します。その他のスレッドには影響はありません。
パラメータ
名前 | 型 | 説明 |
thread | jthread |
再開するスレッド。
|
スレッド・リストの再開
jvmtiError
ResumeThreadList(jvmtiEnv* env,
jint request_count,
const jthread* request_list,
jvmtiError* results)
request_list
配列に指定されたrequest_count
個のスレッドを再開します。 JVM TI中断関数(例: SuspendThreadList
)またはjava.lang.Thread.suspend()
経由で中断されたすべてのスレッドの実行が再開されます。
ライブ段階でしか呼び出せない
いいえ
93
1.0
パラメータ
名前 | 型 | 説明 |
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
と同様)。
パラメータ
名前 | 型 | 説明 |
thread | jthread |
割り込むスレッド。
|
スレッド情報の取得
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
構造体のフィールドに、指定されたスレッドの詳細が入ります。
jvmtiThreadInfo
- スレッド情報構造体
フィールド | 型 | 説明 |
name | char* |
スレッド名。修正UTF-8文字列としてエンコードされる。
|
priority | jint |
スレッドの優先順位。 スレッド優先順位定数jvmtiThreadPriority を参照。
|
is_daemon | jboolean |
デーモン・スレッドかどうか
|
thread_group | jthreadGroup |
このスレッドが属するスレッド・グループ。 スレッドが停止している場合はNULL 。
|
context_class_loader | jobject |
このスレッドに関連付けられているコンテキスト・クラス・ローダー。
|
パラメータ
名前 | 型 | 説明 |
thread | jthread |
照会するスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
info_ptr | jvmtiThreadInfo* |
戻ったとき、指定されたスレッドについての情報が入っている。
エージェントは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)
指定されたスレッドが所有するモニターについての情報を取得します。
ライブ段階でしか呼び出せない
いいえ
10
1.0
パラメータ
名前 | 型 | 説明 |
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)
指定されたスレッドが所有するモニターに関する情報と、それらのモニターをロックしているスタック・フレームの深さを取得します。
ライブ段階でしか呼び出せない
いいえ
153
1.1
jvmtiMonitorStackDepthInfo
- モニター・スタック深さ情報構造体
フィールド | 型 | 説明 |
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* は、サイズ*monitor_info_count_ptr の新しく割り当てられた配列をポイントする。 この配列は、Deallocate を使って解放するべき。 jvmtiMonitorStackDepthInfo のフィールドmonitor で返されるオブジェクトはJNIローカル参照であり、管理する必要がある。
|
現在競合しているモニターの取得
jvmtiError
GetCurrentContendedMonitor(jvmtiEnv* env,
jthread thread,
jobject* monitor_ptr)
指定されたスレッドが、java.lang.Object.wait
を使ってオブジェクトのモニターに入るか、モニターを獲得し直すのを待機している場合に、そのオブジェクトを取得します。
ライブ段階でしか呼び出せない
いいえ
11
1.0
パラメータ
名前 | 型 | 説明 |
thread | jthread |
照会するスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
monitor_ptr | jobject* |
戻ったとき、現在競合しているモニターが入っている。そのようなモニターがない場合はNULLが入っている。
エージェントはjobject へのポインタを渡す。 戻ったとき、jobject が設定されている。 monitor_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 |
いちばん高い優先順位
|
新しいスレッドは、指定のpriority
で、デーモン・スレッドとして起動されます。 有効な場合は、ThreadStart
イベントが送信されます。
スレッドの起動が完了しているため、このスレッドはこの関数が戻る際にライブ状態になっています。ただし、このスレッドがすぐに終了した場合は除きます。
このスレッドのスレッド・グループは無視されます。具体的には、このスレッドは、スレッド・グループに追加されず、Javaプログラミング言語、JVM TIのいずれのレベルでもスレッド・グループのクエリーには表示されません。
このスレッドは、Javaプログラミング言語のクエリーでは表示されませんが、GetAllThreads
やGetAllStackTraces
など、JVM TIのクエリーには含まれます。
proc
を実行すると、新しいスレッドがVMにアタッチされます-- 「VMへのアタッチ」のJNIドキュメントを参照してください。
ライブ段階でしか呼び出せない
いいえ
12
1.0
パラメータ
名前 | 型 | 説明 |
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は、エージェントに対して、スレッドごとの情報を記録するために利用できる、ポインタ・サイズのスレッド・ローカルな記憶領域を提供します。
開始またはライブ段階でしか呼び出せない
いいえ
103
1.0
パラメータ
名前 | 型 | 説明 |
thread | jthread |
このスレッドを格納する。 thread がNULL の場合、現在のスレッドが使用される。
|
data | const void * |
スレッド・ローカルな記憶領域に入力する値。
エージェントがポインタを渡す。 data がNULL の場合、値はNULL に設定される。
|
スレッド・ローカルな記憶領域の取得
jvmtiError
GetThreadLocalStorage(jvmtiEnv* env,
jthread thread,
void** data_ptr)
JVM TIのスレッド・ローカルな記憶領域の値を取得するため、エージェントによって呼び出されます。
開始またはライブ段階でしか呼び出せない
いいえ
102
1.0
パラメータ
名前 | 型 | 説明 |
thread | jthread |
このスレッドから取得する。 thread がNULL の場合、現在のスレッドが使用される。
|
data_ptr | void** |
スレッド・ローカルな記憶領域の値を返すポインタ。 スレッド・ローカルな記憶領域がSetThreadLocalStorage で設定されていない場合、返されるポインタはNULL 。
|
スレッド・グループ
スレッド・グループ関数:
スレッド・グループの型:
トップ・レベルのスレッド・グループの取得
jvmtiError
GetTopThreadGroups(jvmtiEnv* env,
jint* group_count_ptr,
jthreadGroup** groups_ptr)
VM内のトップ・レベルの(親がない)スレッド・グループをすべて返します。
ライブ段階でしか呼び出せない
いいえ
13
1.0
パラメータ
名前 | 型 | 説明 |
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
構造体のフィールドに、指定されたスレッド・グループの詳細が入ります。
ライブ段階でしか呼び出せない
いいえ
14
1.0
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)
このスレッド・グループ内のライブ・スレッドとアクティブなサブグループを取得します。
ライブ段階でしか呼び出せない
いいえ
15
1.0
パラメータ
名前 | 型 | 説明 |
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™仮想マシン仕様のセクション3.6に記載されています。つまり、これらのフレームは、ネイティブ・メソッドを含むメソッドの呼出しに対応しているが、プラットフォーム固有のフレームやVM内部のフレームには対応していません。
JVM TI実装はメソッド呼び出しを使用してスレッドを起動する可能性があるので、対応するフレームがそれらの関数によって提供される情報として、スタック内に含まれる可能性があります。つまり、main()
やrun()
よりも深い位置に表示されるフレームが存在する可能性があります。 ただしこの表現は、スタック・フレームやスタックの深さを使用するすべてのJVM TI機能の間で一貫している必要があります。
スタック・フレーム情報構造体
スタック・フレームに関する情報は次の構造体で戻されます。
typedef struct {
jmethodID method;
jlocation location;
} jvmtiFrameInfo;
jvmtiFrameInfo
- スタック・フレーム情報構造体
フィールド | 型 | 説明 |
method | jmethodID |
このフレーム内で実行されているメソッド。
|
location | jlocation |
このフレーム内で実行されている命令のインデックス。フレームがネイティブ・メソッドを実行している場合は-1 。
|
スタック情報構造体
スタック・フレーム・セットに関する情報は次の構造体で戻されます。
typedef struct {
jthread thread;
jint state;
jvmtiFrameInfo* frame_buffer;
jint frame_count;
} jvmtiStackInfo;
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, NULL);
if (err == JVMTI_ERROR_NONE) {
printf("Executing method: %s", methodName);
}
}
thread
は、中断することなく、この関数を呼び出すことができます。
位置と行番号のマッピングには、GetLineNumberTable
関数を使用できます。 このマッピングは、遅延してもかまいません。
ライブ段階でしか呼び出せない
いいえ
104
1.0
パラメータ
名前 | 型 | 説明 |
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);
ライブ段階でしか呼び出せない
いいえ
100
1.0
スレッド・リストのスタック・トレースの取得
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
を参照してください。
ライブ段階でしか呼び出せない
いいえ
101
1.0
フレーム・カウントの取得
jvmtiError
GetFrameCount(jvmtiEnv* env,
jthread thread,
jint* count_ptr)
指定されたスレッドの呼出しスタックに現在入っているフレームの数を取得します。
アクティブにバイト・コードを実行しているスレッド(現在のスレッドではなく、中断されていないスレッドなど)のためにこの関数が呼び出された場合、一時的な情報が返されます。
ライブ段階でしか呼び出せない
いいえ
16
1.0
パラメータ
名前 | 型 | 説明 |
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イベントを生成しません。
ライブ段階でしか呼び出せない
いいえ
80
1.0
パラメータ
名前 | 型 | 説明 |
thread | jthread |
ポップする現在のフレームのスレッド。
|
フレームの位置の取得
jvmtiError
GetFrameLocation(jvmtiEnv* env,
jthread thread,
jint depth,
jmethodID* method_ptr,
jlocation* location_ptr)
Javaプログラミング言語のフレームについて、現在実行中の命令の位置を返します。
ライブ段階でしか呼び出せない
いいえ
19
1.0
パラメータ
名前 | 型 | 説明 |
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プログラミング言語のメソッドに対応するフレームだけが通知を受信できます。
指定されたスレッドは、中断されているか、現在のスレッドでなければいけません。
ライブ段階でしか呼び出せない
いいえ
20
1.0
パラメータ
名前 | 型 | 説明 |
thread | jthread |
フレームのポップ・イベントが生成されるフレームのスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
depth | jint |
フレームのポップ・イベントが生成されるフレームの深さ。
|
早期復帰の強制
早期復帰の強制の関数:
これらの関数を使うと、エージェントは、実行中の任意のポイントでの復帰をメソッドに強制できます。 早期復帰するメソッドを被呼出しメソッドと呼びます。 被呼出しメソッドは、Java™仮想マシン仕様のセクション3.6に定義されているとおり、関数の呼出し時に、指定されたスレッドの現在のメソッドになります。
指定されたスレッドは、中断されているか、現在のスレッドでなければいけません。 メソッドの復帰は、Javaプログラミング言語のコードの実行がこのスレッド上で再開されたときに行われます。 これらの関数のいずれかを呼び出してからスレッドの実行が再開されるまでの間のスタックの状態は未定義です。
被呼出しメソッドでは、これ以上の命令は実行されません。 特に、最終的にブロックは実行されません。 ノート: これにより、アプリケーション内で整合性のない状態が発生することがあります。
被呼出しメソッドを呼び出すことによって獲得されたロック(これがsynchronized
メソッドの場合)と、被呼出しメソッド内のsynchronized
ブロックに入ることによって獲得されたロックは解放されます。 ノート: これは、ネイティブ・ロックやjava.util.concurrent.locks
ロックには適用されません。
通常復帰の場合と同様に、MethodExit
などのイベントが生成されます。
被呼出しメソッドは、非ネイティブのJavaプログラミング言語のメソッドとします。 スタック上にフレームが1つだけある状態でスレッドへの強制復帰を行なった場合、スレッドが再開時に終了します。
早期復帰の強制 - オブジェクト型
jvmtiError
ForceEarlyReturnObject(jvmtiEnv* env,
jthread thread,
jobject value)
この関数を使うと、結果の型がObject
またはObject
のサブクラスであるメソッドから復帰できます。
ライブ段階でしか呼び出せない
いいえ
81
1.1
パラメータ
名前 | 型 | 説明 |
thread | jthread |
現在のフレームが早期復帰するスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
value | jobject |
被呼出しフレームの戻り値。 オブジェクトまたはNULL 。
|
早期復帰の強制 - 整数型
jvmtiError
ForceEarlyReturnInt(jvmtiEnv* env,
jthread thread,
jint value)
この関数を使うと、結果の型がint
、short
、char
、byte
、boolean
のいずれかであるメソッドから復帰できます。
ライブ段階でしか呼び出せない
いいえ
82
1.1
パラメータ
名前 | 型 | 説明 |
thread | jthread |
現在のフレームが早期復帰するスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
value | jint |
被呼出しフレームの戻り値。
|
早期復帰の強制 - 長整数型
jvmtiError
ForceEarlyReturnLong(jvmtiEnv* env,
jthread thread,
jlong value)
この関数を使うと、結果の型がlong
であるメソッドから復帰できます。
ライブ段階でしか呼び出せない
いいえ
83
1.1
パラメータ
名前 | 型 | 説明 |
thread | jthread |
現在のフレームが早期復帰するスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
value | jlong |
被呼出しフレームの戻り値。
|
早期復帰の強制 - 浮動小数点数型
jvmtiError
ForceEarlyReturnFloat(jvmtiEnv* env,
jthread thread,
jfloat value)
この関数を使うと、結果の型がfloat
であるメソッドから復帰できます。
ライブ段階でしか呼び出せない
いいえ
84
1.1
パラメータ
名前 | 型 | 説明 |
thread | jthread |
現在のフレームが早期復帰するスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
value | jfloat |
被呼出しフレームの戻り値。
|
早期復帰の強制 - 倍精度浮動小数点数型
jvmtiError
ForceEarlyReturnDouble(jvmtiEnv* env,
jthread thread,
jdouble value)
この関数を使うと、結果の型がdouble
であるメソッドから復帰できます。
ライブ段階でしか呼び出せない
いいえ
85
1.1
パラメータ
名前 | 型 | 説明 |
thread | jthread |
現在のフレームが早期復帰するスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
value | jdouble |
被呼出しフレームの戻り値。
|
早期復帰の強制 - void型
jvmtiError
ForceEarlyReturnVoid(jvmtiEnv* env,
jthread thread)
この関数を使うと、結果の型を持たないメソッドから復帰できます。 つまり、被呼出しメソッドがvoid
と宣言されていなければいけません。
ライブ段階でしか呼び出せない
いいえ
86
1.1
パラメータ
名前 | 型 | 説明 |
thread | jthread |
現在のフレームが早期復帰するスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
ヒープ
ヒープ関数:
ヒープの関数型:
ヒープの型:
ヒープのフラグおよび定数:
これらの関数は、ヒープの分析に使用されます。 ヒープ内のオブジェクトの表示、これらのオブジェクトへのタグ付けなどの機能があります。
タグは、オブジェクトに関連付けられる値です。 タグは、エージェントにより、SetTag
関数を使用して明示的に設定されます。または、jvmtiHeapIterationCallback
などのコールバック関数によって設定されます。
タグは環境に対してローカルです。つまり、ある環境のタグを別の環境で表示することはできません。
jlong
値であるタグを使えば、オブジェクトを単純にマークしたり、詳細情報へのポインタを格納したりできます。 タグ付けされていないオブジェクトのタグはゼロになります。 タグをゼロに設定すると、オブジェクトのタグ付けが解除されます。
ヒープ・コールバック関数
ヒープ関数は、ヒープ内での反復処理とオブジェクト参照の再帰的な追跡を行い、エージェントが指定したコールバック関数を使って情報提供を行います。
これらのヒープ・コールバック関数は次の制限に準拠する必要があります。これらのコールバックはJNI関数を使用してはいけません。 これらのコールバックは、コールバック安全な関数(そのような使用を明確に許可している関数)以外のJVM TI関数を使用してはいけません(rawモニター関数、メモリー管理関数、環境ローカル・ストレージ関数を参照)。
実装は、内部スレッド上または反復関数を呼び出したスレッド上で、コールバックを呼び出せます。 ヒープ・コールバックはシングル・スレッドです。一度に呼び出されるコールバックの数は最大1個になります。
ヒープ・フィルタ・フラグを使うと、オブジェクトまたはそのクラスのタグの状態に基づいて報告を行わないようにすることができます。 フラグが設定されていない場合(jint
がゼロの場合)、オブジェクトのフィルタ・リングは行われません。
ヒープ・フィルタ・フラグ
定数 | 値 | 説明 |
JVMTI_HEAP_FILTER_TAGGED | 0x4 |
タグ付きのオブジェクトをフィルタ・リングする。 タグの付いたオブジェクトが除外される。
|
JVMTI_HEAP_FILTER_UNTAGGED | 0x8 |
タグなしのオブジェクトをフィルタ・リングする。 タグの付いていないオブジェクトが除外される。
|
JVMTI_HEAP_FILTER_CLASS_TAGGED | 0x10 |
タグ付きのクラスを持つオブジェクトをフィルタ・リングする。 タグの付いたクラスのオブジェクトが除外される。
|
JVMTI_HEAP_FILTER_CLASS_UNTAGGED | 0x20 |
タグなしのクラスを持つオブジェクトをフィルタ・リングする。 タグの付いていないクラスのオブジェクトが除外される。
|
ヒープ・コールバックによって返されるヒープ・ビジット制御フラグを使うと、反復処理を中止できます。 また、ヒープ参照コールバックは、トラバース対象となる参照のグラフを取り除くために使うこともできます(JVMTI_VISIT_OBJECTS
を設定しない)。
ヒープ・ビジット制御フラグ
定数 | 値 | 説明 |
JVMTI_VISIT_OBJECTS | 0x100 |
あるオブジェクトをビジットする際にこのコールバックがFollowReferences によって起動されたものであった場合、そのオブジェクトの参照をトラバースする。 それ以外の場合は無視される。
|
JVMTI_VISIT_ABORT | 0x8000 |
反復処理を中止。 ほかのすべてのビットを無視する。
|
ヒープ参照の列挙は、報告対象の参照の種類を記述する目的で、ヒープ参照コールバックとプリミティブ・フィールド・コールバックによって提供されます。
ヒープ参照の列挙(jvmtiHeapReferenceKind
)
定数 | 値 | 説明 |
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 |
ヒープ・ルート参照: ほかのヒープ・ルート参照。
|
プリミティブ型の単一文字型記述子の定義。
プリミティブ型の列挙(jvmtiPrimitiveType
)
定数 | 値 | 説明 |
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;
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;
jvmtiHeapReferenceInfoArray
- 配列参照用の参照情報構造体
フィールド | 型 | 説明 |
index | jint |
配列のインデックス。
|
定数プール参照用の参照情報構造体
JVMTI_HEAP_REFERENCE_CONSTANT_POOL
の参照に対して返される参照情報。
typedef struct {
jint index;
} jvmtiHeapReferenceInfoConstantPool;
jvmtiHeapReferenceInfoConstantPool
- 定数プール参照用の参照情報構造体
フィールド | 型 | 説明 |
index | jint |
クラスの定数プール内のインデックス。 Java™仮想マシン仕様のセクション4.4を参照。
|
局所変数参照用の参照情報構造体
JVMTI_HEAP_REFERENCE_STACK_LOCAL
の参照に対して返される参照情報。
typedef struct {
jlong thread_tag;
jlong thread_id;
jint depth;
jmethodID method;
jlocation location;
jint slot;
} jvmtiHeapReferenceInfoStackLocal;
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;
jvmtiHeapReferenceInfoJniLocal
- JNIローカル参照用の参照情報構造体
フィールド | 型 | 説明 |
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;
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
は、ビジットされるオブジェクトは制御しませんが、コールバックによって報告されるオブジェクトおよびプリミティブ値は制御します。 たとえば、設定された唯一のコールバックがarray_primitive_value_callback
であり、klass
がバイト配列のクラスに設定された場合、バイト配列のみが報告されます。 以上をまとめたのが次の表です。
この関数の実行中、ヒープの状態は変化しません。オブジェクトの割当てやガベージ・コレクションは行われず、オブジェクトの状態(保持された値を含む)は変化しません。 このため、Javaプログラミング言語コードを実行するスレッド、Javaプログラミング言語コードの実行を再開しようとしているスレッド、およびJNI関数を実行しようとしているスレッドは通常ストールされます。
ライブ段階でしか呼び出せない
いいえ
115
1.1
パラメータ
名前 | 型 | 説明 |
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
は、ビジットされるオブジェクトは制御しませんが、コールバックによって報告されるオブジェクトおよびプリミティブ値は制御します。 たとえば、設定された唯一のコールバックがarray_primitive_value_callback
であり、klass
がバイト配列のクラスに設定された場合、バイト配列のみが報告されます。 これをまとめたのが下の表です(これをFollowReferences
と比較してください)。
この関数の実行中、ヒープの状態は変化しません。オブジェクトの割当てやガベージ・コレクションは行われず、オブジェクトの状態(保持された値を含む)は変化しません。 このため、Javaプログラミング言語コードを実行するスレッド、Javaプログラミング言語コードの実行を再開しようとしているスレッド、およびJNI関数を実行しようとしているスレッドは通常ストールされます。
ライブ段階でしか呼び出せない
いいえ
116
1.1
パラメータ
名前 | 型 | 説明 |
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
関数を使用します。 タグが設定されていないオブジェクトは、タグ値としてゼロを返します。
開始またはライブ段階でしか呼び出せない
いいえ
106
1.0
パラメータ
名前 | 型 | 説明 |
object | jobject |
タグが取得されるオブジェクト。
|
tag_ptr | jlong* |
戻ったとき、参照される長整数値にタグ値が設定されている。
エージェントはjlong へのポインタを渡す。 戻ったとき、jlong が設定されている。 |
タグの設定
jvmtiError
SetTag(jvmtiEnv* env,
jobject object,
jlong tag)
オブジェクトに関連付けられているタグを設定します。 タグは長整数値で、通常、オブジェクト情報の一意の識別子またはポインタを格納するために使用されます。 タグの表示には、GetTag
関数を使用します。
開始またはライブ段階でしか呼び出せない
いいえ
107
1.0
タグを使ったオブジェクトの取得
jvmtiError
GetObjectsWithTags(jvmtiEnv* env,
jint tag_count,
const jlong* tags,
jint* count_ptr,
jobject** object_result_ptr,
jlong** tag_result_ptr)
ヒープ内の指定されたタグを持つオブジェクトを返します。 オブジェクトとタグの並行配列の形式になります。
ライブ段階でしか呼び出せない
いいえ
114
1.0
パラメータ
名前 | 型 | 説明 |
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
イベントが送信されているという保証はありません。 特に、ファイナライズ待ちのオブジェクトが解放されない可能性があります。
ライブ段階でしか呼び出せない
いいえ
108
1.0
ヒープ(1.0)
ヒープ(1.0)の関数:
ヒープ(1.0)の関数型:
ヒープ(1.0)の型:
これらの関数およびデータ型は元のJVM TI Version 1.0で導入されたものであり、より強力で柔軟性の高いバージョンで置き換えられました。新しいバージョンの特徴を次に示します。
-
プリミティブ値(Strings、配列、およびプリミティブ・フィールドの値)へのアクセスを可能にする
-
参照側のタグを設定できるようにする。このため、より効率的なローカライズされた参照グラフの構築が可能となる
-
より広範なフィルタ・リング機能を提供する
-
拡張可能である。このため、JVM TIの将来のバージョンで拡張を施すことができる
現在のヒープ関数を使用してください。
ヒープ・オブジェクトのフィルタの列挙(jvmtiHeapObjectFilter
)
定数 | 値 | 説明 |
JVMTI_HEAP_OBJECT_TAGGED | 1 |
タグ付きオブジェクトのみ。
|
JVMTI_HEAP_OBJECT_UNTAGGED | 2 |
タグなしオブジェクトのみ。
|
JVMTI_HEAP_OBJECT_EITHER | 3 |
タグ付きオブジェクトまたはタグなしオブジェクト。
|
ヒープ・ルートの種類の列挙(jvmtiHeapRootKind
)
定数 | 値 | 説明 |
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 |
その他。
|
オブジェクト参照の列挙(jvmtiObjectReferenceKind
)
定数 | 値 | 説明 |
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™仮想マシン仕様のセクション4.4を参照。
|
反復制御の列挙(jvmtiIterationControl
)
定数 | 値 | 説明 |
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回ずつ行われます。これは、参照循環が存在する場合や参照元へのパスが複数存在する場合でも言えることです。 参照元と参照先との間の参照は複数存在する可能性があります。これらを区別するには、jvmtiObjectReferenceCallback.reference_kind
およびjvmtiObjectReferenceCallback.referrer_index
を使用します。 あるオブジェクトのコールバックは必ず、その参照元のコールバックの後で発生します。
報告されるオブジェクト参照については、FollowReferences
を参照してください。
この関数の実行中、ヒープの状態は変化しません。オブジェクトの割当てやガベージ・コレクションは行われず、オブジェクトの状態(保持された値を含む)は変化しません。 このため、Javaプログラミング言語コードを実行するスレッド、Javaプログラミング言語コードの実行を再開しようとしているスレッド、およびJNI関数を実行しようとしているスレッドは通常ストールされます。
ライブ段階でしか呼び出せない
いいえ
109
1.0
パラメータ
名前 | 型 | 説明 |
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_ref_callback
コールバックが呼び出されます。 オブジェクトは複数の理由でルート・オブジェクトになる可能性がありますが、その場合、対応するコールバックが理由ごとに呼び出されます。
各オブジェクト参照について、そのオブジェクト参照を記述する目的でobject_ref_callback
コールバック関数が呼び出されます。 コールバックの呼出しは、参照元からの参照ごとに1回ずつ行われます。これは、参照循環が存在する場合や参照元へのパスが複数存在する場合でも言えることです。 参照元と参照先との間の参照は複数存在する可能性があります。これらを区別するには、jvmtiObjectReferenceCallback.reference_kind
およびjvmtiObjectReferenceCallback.referrer_index
を使用します。 あるオブジェクトのコールバックは必ず、その参照元のコールバックの後で発生します。
報告されるオブジェクト参照については、FollowReferences
を参照してください。
ルートは、常に、オブジェクト参照が報告される前に、プロファイラに報告されます。 つまり、object_ref_callback
は、すべてのルートに対して適切なコールバックが呼び出されるまで、呼び出されません。 object_ref_callback
がNULL
と指定されている場合、この関数は、プロファイラにルート・オブジェクトを報告したあと、終了します。
この関数の実行中、ヒープの状態は変化しません。オブジェクトの割当てやガベージ・コレクションは行われず、オブジェクトの状態(保持された値を含む)は変化しません。 このため、Javaプログラミング言語コードを実行するスレッド、Javaプログラミング言語コードの実行を再開しようとしているスレッド、およびJNI関数を実行しようとしているスレッドは通常ストールされます。
ライブ段階でしか呼び出せない
いいえ
110
1.0
パラメータ
名前 | 型 | 説明 |
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関数を実行しようとしているスレッドは通常ストールされます。
ライブ段階でしか呼び出せない
いいえ
111
1.0
クラスのインスタンスの反復
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関数を実行しようとしているスレッドは通常ストールされます。
ライブ段階でしか呼び出せない
いいえ
112
1.0
局所変数
局所変数関数:
これらの関数は、局所変数の値を取得または設定するために使います。 変数は、変数の値を含んでいるフレームの深さと、そのフレーム内の変数のスロット番号によって識別されます。 変数からスロット番号へのマッピングは、関数GetLocalVariableTable
を使って取得できます。
局所変数の取得 - オブジェクト型
jvmtiError
GetLocalObject(jvmtiEnv* env,
jthread thread,
jint depth,
jint slot,
jobject* value_ptr)
この関数を使うと、型がObject
またはObject
のサブクラスである局所変数の値を取得できます。
ライブ段階でしか呼び出せない
いいえ
21
1.0
パラメータ
名前 | 型 | 説明 |
thread | jthread |
変数の値を含むフレームのスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
depth | jint |
変数の値を含むフレームの深さ。
|
slot | jint |
変数のスロット番号。
|
value_ptr | jobject* |
戻ったとき、変数の値をポイントする。
エージェントはjobject へのポインタを渡す。 戻ったとき、jobject が設定されている。 value_ptr から返されるオブジェクトはJNIローカル参照であり、管理する必要がある。
|
局所インスタンスの取得
jvmtiError
GetLocalInstance(jvmtiEnv* env,
jthread thread,
jint depth,
jobject* value_ptr)
この関数を使うと、静的でないフレームからスロット0 (「this
」オブジェクト)の局所オブジェクト変数の値を取得できます。 この関数は、ネイティブ・メソッドのフレームから「this
」オブジェクトを取得しますが、この場合、GetLocalObject()
はJVMTI_ERROR_OPAQUE_FRAME
を返します。
ライブ段階でしか呼び出せない
いいえ
155
1.2
パラメータ
名前 | 型 | 説明 |
thread | jthread |
変数の値を含むフレームのスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
depth | 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
のいずれかである局所変数の値を取得できます。
ライブ段階でしか呼び出せない
いいえ
22
1.0
パラメータ
名前 | 型 | 説明 |
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
である局所変数の値を取得できます。
ライブ段階でしか呼び出せない
いいえ
23
1.0
パラメータ
名前 | 型 | 説明 |
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
である局所変数の値を取得できます。
ライブ段階でしか呼び出せない
いいえ
24
1.0
パラメータ
名前 | 型 | 説明 |
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
である局所変数の値を取得できます。
ライブ段階でしか呼び出せない
いいえ
25
1.0
パラメータ
名前 | 型 | 説明 |
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
のサブクラスである局所変数の値を設定できます。
ライブ段階でしか呼び出せない
いいえ
26
1.0
パラメータ
名前 | 型 | 説明 |
thread | jthread |
変数の値を含むフレームのスレッド。 thread がNULL の場合、現在のスレッドが使用される。
|
depth | jint |
変数の値を含むフレームの深さ。
|
slot | jint |
変数のスロット番号。
|
value | jobject |
変数の新しい値。
|