Java

JavaTM Virtual Machine Debug Interface リファレンス

目次

はじめに
JVMDI の関数の使用法
エラー
イベント
VM および JVMDI クライアントの起動


はじめに

注: J2SE 5.0 では、JVMDI は推奨されていません。その代わりに、JVMTI を使用する必要があります。

JavaTM Virtual Machine Debug Interface (JVMDI) は、デバッガやその他のプログラミングツールにより使用されるプログラミングインタフェースです。このインタフェースは、JavaTM 仮想マシンで動作するアプリケーションの状態検査と実行制御の両方の機能を提供します。

JVMDI は、双方向のインタフェースです。JVMDI クライアントは、知りたい状態の発生状況について、イベントを介して通知を受け取ることができます。JVMDI は、イベントに応答して、またはイベントからは独立して、さまざまな関数を使ってアプリケーションへの照会および制御を実行できます。

JVMDI クライアントは、デバッグされているアプリケーションと同じ仮想マシン上で動作し、ネイティブインタフェースを使って JVMDI にアクセスします。ネイティブのインプロセスインタフェースにより、デバッグツール側への侵入は最小限に抑えながら、最大限の制御が可能になります。通常、JVMDI クライアントは比較的コンパクトです。JVMDI クライアントは、ターゲットアプリケーションの通常の実行を妨げることなく、デバッガの機能の大部分を実装する別のプロセスによって制御できます。

JVMDI は、Java Platform Debugger Architecture の一番下の層です。この役割は JVMTI によって処理されるようになりました。このアーキテクチャには、より高いレベルの、アウトプロセスのデバッガインタフェースが含まれています。多くのデバッガツールには、JVMDI よりも高いレベルのインタフェースの方が適しています。Java Platform Debugger Architecture の詳細については、このリリースの Java Platform Debugger Architecture のドキュメントおよび Java Platform Debugger Architecture の Web サイトを参照してください。


JVMDI の関数の使用法

関数および定数を定義する場合は、

        #include <jvmdi.h>
をソースコードに追加してください。

Java Native Interface (JNI) の関数と同様に、JVMDI の関数には、関数テーブルを使ってアクセスします。JVMDI の関数テーブルは、JNI の GetEnv 関数を使って取得できます。たとえば、次のコードは、バージョン 1 の JVMDI 用の関数テーブルを取得します。

        JVMDI_Interface_1 *jvmdi;
        ...
        (*jvm)->GetEnv(jvm, &jvmdi, JVMDI_VERSION_1);

JVMDI の関数は、復帰状態を表す jvmdiError 値を常に返します。関数によっては、呼び出し側の関数で指定されたポインタにより、これ以外の値を返すことも可能です。JVMDI の関数の中にはメモリを割り当てるものがありますが、この場合はプログラム内でそのメモリを明示的に解放しなければなりません。これについては、個々の関数の説明に明記されています。空のリスト、配列、シーケンスなどは、割り当てられた長さがゼロの配列 (null ではない) として返されます。

JVMDI の関数は、JNI 参照を使ってオブジェクトを識別します。JVMDI の関数に渡される参照は、グローバルでもローカルでもかまいませんが、強い参照でなければなりません。JVMDI の関数によって返される参照はすべて、強いグローバル参照です。

JVMDI 関数がエラーに遭遇した場合は (戻り値が JVMDI_ERROR_NONE 以外)、引数ポインタにより参照されるメモリ値は未定義です。しかし、メモリおよびグローバル参照は何も割り当てられません。

JVMDI では、JNI で定義されているデータ型を、次のように拡張しています。jthread および jthreadGroupjobject のサブタイプであり、対応するオブジェクトを表します。jframeID は、中断されたスレッドまたは現在のスレッドの単一のスタックフレームを表すポインタ型です (スレッドが再開されると無効になる)。jlocation は、64 ビットの符号なしの値で、メソッド内で単調に増加する実行可能位置を表します。jvmdiErrorjint であり、その用途はすでに説明したとおりです。

JVMDI の関数は、次のようなカテゴリに分類されます。


メモリ管理

JVMDI の多くの関数では、メモリの割り当てを必要とします。デフォルトでは、メモリは malloc() などのプラットフォーム固有のメモリ割り当て関数で割り当てられます。JVMDI に基づいて構築するシステムでは、独自のメモリ割り当て機構を提供できます。独自のメモリ割り当て機構を使用すれば、たとえば、メモリが少なくなってもデバッガが処理を続行できるように事前にメモリを割り当てておくといったことが可能になります。また、デフォルトのメモリ割り当て関数を、デバッガ固有の関数に置き換えることで、内部でメモリ管理関数を実行中にアプリケーションのスレッドが中断している間、デバッガのスレッドが malloc に入ることができないシステム上で、デッドロック発生の可能性を減らすことができます。


割り当てフックの設定

jvmdiError
SetAllocationHooks(JVMDI_AllocHook ahook, JVMDI_DeallocHook dhook)

メモリ割り当て関数とメモリ解放関数を設定します。フック関数は以下のように定義されます。

typedef jvmdiError (*JVMDI_AllocHook)(jlong size, jbyte** memPtr)
typedef jvmdiError (*JVMDI_DeallocHook)(jbyte* buffer)

JVMDI は、メモリを割り当てるときは ahook を呼び出し、メモリを解放するときは dhook を呼び出します。この指定を行うと、JVMDI のデフォルトのメモリアロケータは無効になります。デフォルトのアロケータに戻すには、ahook および dhooknull に設定して SetAllocationHooks を呼び出します。

ahook 関数では、割り当てるバイト数を size で受け取り、そのメモリを memPtr で返すようにします。戻り値としては、null ポインタが引き渡された場合は JVMDI_ERROR_NULL_POINTER を、メモリ割り当て要求を受け付けることができない場合は JVMDI_ERROR_OUT_OF_MEMORY を、それ以外の場合は JVMDI_ERROR_NONE を返すようにします。

dhook 関数では、解放するメモリを buffer で受け取るようにします。戻り値としては、null ポインタが引き渡された場合は JVMDI_ERROR_NULL_POINTER を、それ以外の場合は JVMDI_ERROR_NONE を返すようにします。

パラメータ:

ahook
メモリの割り当てに使用する関数、または null (デフォルトのアロケータに戻す場合)
dhook
メモリの解放に使用する関数、または null (デフォルトのアロケータに戻す場合)

SetAllocationHooks は、常に JVMDI_ERROR_NONE を返します。


メモリの割り当て

jvmdiError
Allocate(jlong size, jbyte** memPtr)

JVMDI のアロケータを使用して、メモリの領域を割り当てます。割り当てられたメモリは、Deallocate によって解放してください。

パラメータ:

size
割り当てるバイト数
memPtr
戻ったとき、SetAllocationHooks で指定されたアロケータによって割り当てられたメモリの先頭を指すポインタ

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

メモリの解放

jvmdiError
Deallocate(jbyte* mem)
JVMDI のアロケータを使用して、mem を解放します。この関数は、JVMDI の関数によって割り当てられて返されたメモリ、または Allocate を使用して割り当てられたメモリを解放するために使用します。

パラメータ:

mem
割り当てられたメモリの先頭を指すポインタ

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ


スレッド実行関数


スレッドステータスの取得

jvmdiError
GetThreadStatus(jthread thread, jint *threadStatusPtr, jint *suspendStatusPtr)

スレッドのステータス情報を取得します。

パラメータ:

thread
照会するスレッド
threadStatusPtr
戻ったとき、スレッドの現在のステータスをポイントする。スレッドを中断した場合、中断前のスレッドのステータスが返されます。スレッドのステータスは次の値のうちのどれかで表されます。
JVMDI_THREAD_STATUS_UNKNOWN
スレッドのステータスは不明

JVMDI_THREAD_STATUS_ZOMBIE
スレッドは実行を完了

JVMDI_THREAD_STATUS_RUNNING
スレッドは実行可能

JVMDI_THREAD_STATUS_SLEEPING
スレッドはスリープ中(Thread.sleep() が呼び出された)

JVMDI_THREAD_STATUS_MONITOR
スレッドは同期ブロックに入るために待機中

JVMDI_THREAD_STATUS_WAIT
スレッドは待機中(Object.wait() が呼び出された)
suspendStatusPtr
戻ったとき、中断についての情報をポイントする。中断ステータスは、ビットフラグを含まないか、または 1 つ以上のビットフラグを組み合わせたもの

JVMDI_SUSPEND_STATUS_SUSPENDED
スレッドは中断されている(java.lang.Thread.suspend()SuspendThread、または SuspendThreadList が呼び出された)。

JVMDI_SUSPEND_STATUS_BREAK
スレッドはブレークポイントに達して中断された。このビットは、スレッドが現在のスレッドであるか、またはスレッドが中断されている場合にだけ有効である
この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_NULL_POINTER
無効なポインタ

すべてのスレッドの取得

jvmdiError
GetAllThreads(jint *threadsCountPtr, jthread **threadsPtr)

仮想マシンに認識されている実行中のすべてのスレッドを取得します。VM に接続されていないネイティブスレッドは、返されるリストに含まれません。

パラメータ:

threadsCountPtr
戻ったとき、スローされる例外の数をポイントする
threadsPtr
戻ったとき、参照 (実行中のスレッドごとに 1 つずつ) の配列をポイントする。配列内のスレッドは、JNI のグローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある。返されたスレッドの配列は、Deallocate を使って解放する必要がある
この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ


スレッドの中断

jvmdiError
SuspendThread(jthread thread)

指定されたスレッドを中断します。呼び出し側スレッドが指定されている場合、この関数は、ほかのスレッドが ResumeThread または ResumeThreadList を呼び出すまで戻りません。

パラメータ:

thread
中断するスレッド

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_THREAD_SUSPENDED
スレッドはすでに中断されている

スレッドリストの中断

jvmdiError
SuspendThreadList(jint reqCount, jthread *reqList, jvmdiError *results)
reqList 配列で指定された reqCount スレッドを中断します。呼び出し側スレッドが reqList 配列で指定されている場合、この関数は、ほかのスレッドが ResumeThread または ResumeThreadList を呼び出すまで戻りません。

パラメータ:

reqCount
中断するスレッドの数
reqList
中断するスレッドのリスト
results
スレッドごとの中断結果のリスト

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_ILLEGAL_ARGUMENT
reqCount はゼロ (0) 未満

関数の戻り値にスレッドごとのエラー状態は含まれません。スレッドごとのエラー状態は結果配列を介して返されます。

指定したスレッドの結果配列要素には、汎用エラー、または次のエラーのどれかが含まれます。

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_THREAD_SUSPENDED
スレッドはすでに中断されている

JVMDI_ERROR_NULL_POINTER
無効なポインタ

スレッドの再開

jvmdiError
ResumeThread(jthread thread)

中断されているスレッドの実行を再開します。java.lang.Thread.suspend()SuspendThread、または SuspendThreadList によって中断されたスレッドの実行を再開します。

パラメータ:

thread
再開するスレッド

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_THREAD_NOT_SUSPENDED
スレッドは中断されていない

JVMDI_ERROR_INVALID_TYPESTATE
スレッドの状態が変更されたため、不整合が生じている

スレッドリストの再開

jvmdiError
ResumeThreadList(jint reqCount, jthread *reqList, jvmdiError *results)

reqList 配列で指定された reqCount スレッドを再開します。java.lang.Thread.suspend()SuspendThread、または SuspendThreadList によって中断されたスレッドの実行を再開します。

パラメータ:

reqCount
再開するスレッドの数
reqList
再開するスレッドのリスト
results
スレッドごとの再開結果のリスト

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_ILLEGAL_ARGUMENT
reqCount はゼロ (0) 未満

指定したスレッドの結果配列要素には、汎用エラー、または次のエラーのどれかが含まれます。

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_THREAD_NOT_SUSPENDED
スレッドは中断されていない

JVMDI_ERROR_INVALID_TYPESTATE
スレッドの状態が変更されたため、不整合が生じている

JVMDI_ERROR_NULL_POINTER
無効なポインタ

スレッドの停止

jvmdiError
StopThread(jthread thread, jobject exception)

指定された非同期の例外を指定されたスレッドに送ります (java.lang.Thread.stop と同様)。通常、この関数は、指定されたスレッドを、例外 ThreadDeath のインスタンスを使って終了させるために使います。

パラメータ:

thread
停止するスレッド
exception
非同期の例外オブジェクト

この関数は、次のエラーコードのどれかを返します。

JVMDI_ERROR_INVALID_THREAD

スレッドの割り込み

jvmdiError
InterruptThread(jthread thread)

指定されたスレッドに割り込みます (java.lang.Thread.interrupt と同様)。

パラメータ:

thread
割り込むスレッド

この関数は、次のエラーコードのどれかを返します。

JVMDI_ERROR_INVALID_THREAD

スレッド情報の取得

typedef struct {
	char *name;             /* Name in UTF-8 */
	jint priority;
	jboolean is_daemon;
	jthreadGroup thread_group;
	jobject context_class_loader;
} JVMDI_thread_info;

jvmdiError
GetThreadInfo(jthread thread, JVMDI_thread_info *infoPtr)

スレッド情報を取得します。JVMDI_thread_info 構造体のフィールドに、指定されたスレッドの詳細が入ります。

パラメータ:

thread
照会するスレッド
infoPtr
戻ったとき、指定されたスレッドについての情報が入っている。返されるオブジェクト (スレッドグループおよびコンテキストクラスローダ) はグローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある。返されるスレッド名の文字列は、Deallocate を使って解放する必要がある

コンテキストクラスローダを認識しない JDK 1.1 の実装の場合、context_class_loader フィールドは null

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_NULL_POINTER
無効なポインタ

所有モニター情報の取得

typedef struct {
    jint owned_monitor_count;
    jobject *owned_monitors;
} JVMDI_owned_monitor_info;


jvmdiError
GetOwnedMonitorInfo(jthread thread, JVMDI_owned_monitor_info *infoPtr)

指定されたスレッドが所有するモニターについての情報を取得します。JVMDI_owned_monitor_info 構造体のフィールドに、所有するモニターの詳細が入ります。この関数を現在のスレッド以外のスレッドに対して呼び出す場合は、指定するスレッドを中断する必要があります。

この機能はオプションで、すべての仮想マシンに実装しなければならないわけではありません。特定の仮想マシンでサポートされている機能について判別するには、GetCapabilities を使います。

パラメータ:

thread
照会するスレッド
infoPtr
戻ったとき、所有するモニターの情報が入っている。返されるオブジェクト (所有するモニターの配列) はグローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある。配列の入っている owned_monitors バッファは、Deallocate を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_THREAD_NOT_SUSPENDED
呼び出しの前に、thread が中断されている必要がある

JVMDI_ERROR_NOT_IMPLEMENTED
このオプション機能は、この VM に存在しない

現在競合しているモニターの取得

jvmdiError
GetCurrentContendedMonitor(jthread thread, jobject *monitorPtr)

指定されたスレッドが、java.lang.Object.wait を使ってオブジェクトのモニターに入るか、モニターを獲得し直すのを待機している場合に、そのオブジェクトを取得します。この関数を現在のスレッド以外のスレッドに対して呼び出す場合は、指定するスレッドを中断する必要があります。

この機能はオプションで、すべての仮想マシンに実装しなければならないわけではありません。特定の仮想マシンでサポートされている機能について判別するには、GetCapabilities を使います。

パラメータ:

thread
照会するスレッド
monitorPtr
戻ったとき、現在競合しているモニターが入っている。そのようなモニターがない場合は null が入っている。競合するモニターオブジェクトはグローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_THREAD_NOT_SUSPENDED
呼び出しの前に、thread が中断されている必要がある

JVMDI_ERROR_NOT_IMPLEMENTED
このオプション機能は、この VM に存在しない

デバッグスレッドの実行

typedef void (*JVMDI_StartFunction)(void *);
jvmdiError
RunDebugThread(jthread thread, JVMDI_StartFunction proc, void *arg, int priority);

指定されたネイティブ関数を使って、デバッガスレッドの実行を開始します。この開始関数には、1 つの引数 arg と、指定された優先順位が与えられます。この関数を利用すると、java.lang.Thread の特別なサブクラスや java.lang.Runnable の実装者をロードする必要なしに、別のプロセスとの通信を処理したりイベントを処理したりするデバッガスレッドを作成できます。こうして作成されたスレッドは、完全にネイティブとして機能できます。ただし、作成するスレッドには、java.lang.Thread の新しく作成されたインスタンス (引数 thread によって参照される) が必要で、そのインスタンスにスレッドを関連付けます。スレッドオブジェクトは JNI 呼び出しによって作成できますが、デバッグ中のアプリケーションとの相互作用を避けるため、そのような Java コードへの呼び出しはデバッガの初期化中に行うことをお勧めします。

新しいスレッドは、デーモンスレッドとして起動されます。

proc の実行時に、新しいスレッドは VM に接続されます。

パラメータ:

thread
実行するスレッド
proc
開始関数
arg
開始関数への引数
priority
開始されるスレッドの優先順位。java.lang.Thread.setPriority で許可されている、次の任意のスレッド優先順位を使用できる
  • JVMDI_THREAD_MIN_PRIORITY
  • JVMDI_THREAD_NORM_PRIORITY
  • JVMDI_THREAD_MAX_PRIORITY

この関数は、次のエラーコードのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_INVALID_PRIORITY


スレッドグループ


トップレベルのスレッドグループの取得

jvmdiError
GetTopThreadGroups(jint *groupCountPtr, jthreadGroup **groupsPtr)

VM 内のトップレベルの (親がない) スレッドグループをすべて返します。

パラメータ:

groupCountPtr
戻ったとき、トップレベルのスレッドグループの数をポイントする
groupsPtr
戻ったとき、トップレベルののスレッドグループの配列を指すポインタを参照する返されるグループ配列には、グローバル参照が入っており、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある。グループ配列の配列バッファは、Deallocate を使って解放する必要がある

この関数は、次のエラーコードのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

スレッドグループ情報の取得

typedef struct {
    jthreadGroup parent;
    char *name;             /* Name in UTF-8 */
    jint  max_priority;
    jboolean is_daemon;
} JVMDI_thread_group_info;

jvmdiError
GetThreadGroupInfo(jthreadGroup group, JVMDI_thread_group_info *infoPtr)

スレッドグループの情報を取得します。JVMDI_thread_group_info 構造体のフィールドに、指定されたスレッドグループの詳細が入ります。

パラメータ:

group
照会するスレッドグループ
infoPtr
戻ったとき、指定されたスレッドグループについての情報が入っている。返されるスレッドグループの親はグローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある。返されるスレッドグループ名の文字列は、Deallocate を使って解放する必要がある

この関数は、次のエラーコードのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_THREAD_GROUP

子スレッドグループの取得

jvmdiError
GetThreadGroupChildren(jthreadGroup group,
                 jint *threadCountPtr, jthread **threadsPtr,
                 jint *groupCountPtr, jthreadGroup **groupsPtr)
指定されたスレッドグループ内で作成されたライブスレッドおよびアクティブなスレッドグループを取得します。スレッドが開始しており、まだ停止していない場合、そのスレッドはライブスレッドです。アクティブなスレッドグループについては、「java.lang.ThreadGroup」を参照してください。

パラメータ:

group
照会するグループ
threadCountPtr
戻ったとき、所有されているライブスレッドの数をポイントする
threadsPtr
戻ったとき、所有されているライブスレッド配列へのポインタを参照する。返されるスレッド配列には、グローバル参照が入っており、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある。スレッド配列のバッファは、Deallocate を使って解放する必要がある
groupCountPtr
戻ったとき、アクティブな子スレッドグループの数をポイントする
groupsPtr
戻ったとき、アクティブな子スレッドグループの配列へのポインタを参照する。返されるグループ配列には、グローバル参照が入っており、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある。グループ配列の配列バッファは、Deallocate を使って解放する必要がある

この関数は、次のエラーコードのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_THREAD_GROUP


スタックフレームのアクセス


スレッドのフレームカウントの取得

jvmdiError
GetFrameCount(jthread thread, jint *countPtr)

指定されたスレッドの呼び出しスタックに現在入っているフレームの数を取得します。

この関数を現在のスレッド以外のスレッドに対して呼び出す場合は、指定するスレッドを中断する必要がある

パラメータ:

thread
照会するスレッド
countPtr
戻ったとき、呼び出しスタック内のフレームの数をポイントする
この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_THREAD_NOT_SUSPENDED
スレッドは中断されていない

スレッドの現在のフレームの取得

jvmdiError
GetCurrentFrame(jthread thread, jframeID *framePtr)

thread の現在のスタックフレームの jframeID 値を取得し、framePtr を使って返します。

この関数を現在のスレッド以外のスレッドに対して呼び出す場合は、指定するスレッドを中断する必要があります。返されるフレーム ID 値は、thread が実行を再開するまでの間のみ有効です。スレッドは、Java プログラミング言語または JNI メソッド内に存在する必要があります。

パラメータ:

thread
照会するスレッド
framePtr
戻ったとき、このスレッドの現在のスタックフレームのフレーム ID をポイントする
この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_THREAD_NOT_SUSPENDED
スレッドは中断されていない

JVMDI_ERROR_NO_MORE_FRAMES
呼び出しスタックに Java または JNI フレームがなくなった

スレッドのスタックからのフレームのポップ

jvmdiError
PopFrame(jthread thread)

thread スタックの最上位のスタックをポップします。フレームをポップすると、最上位のスタックフレームの呼び出し側のフレームに移動します。スレッドが再開されると、スレッドの状態は、メソッドが呼び出される直前の状態にリセットされます。オペランドスタックは回復します (objectref (適切な場合) および引数が再度追加されます)。ただし、呼び出し先のメソッドで発生した引数の変更内容は保持されます。実行を続行すると、最初の実行指示が呼び出しとなります。

PopFrame の呼び出しとスレッドの再開の間、スタックの状態は未定義です。最初のフレームよりも前にフレームをポップするには、次の 3 つの手順を繰り返す必要があります。

ポップされたフレームに対するロックは、ポップ時に解放されます。これは、ポップされた同期化メソッドや、その中の同期化ブロックにも当てはまります。

最終的に、ブロックは実行されません。

グローバル状態への変更には対応しません。

この関数を現在のスレッド以外のスレッドに対して呼び出す場合は、指定するスレッドを中断する必要があります。スレッドは、Java プログラミング言語または JNI メソッド内に存在する必要があります。

このスレッドのすべてのフレーム ID は無効です。

この関数は、JVMDI イベントを生成しません。

ネイティブフレームはポップされないことがあります。また、呼び出し側がネイティブコードの場合は Java フレームもポップされないことがあります。

この機能はオプションで、すべての仮想マシンに実装しなければならないわけではありません。特定の仮想マシンでこの機能がサポートされているかどうかを判別するには、GetCapabilitiescan_pop_frame を調べてください。

パラメータ:

thread
ポップするトップフレームのスレッド
この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_OPAQUE_FRAME
frame はネイティブフレームではない

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_THREAD_NOT_SUSPENDED
スレッドが中断されていない、または現在のスレッド

JVMDI_ERROR_NO_MORE_FRAMES
呼び出しスタックに Java プログラミング言語のフレームがなくなった。

JVMDI_ERROR_NOT_IMPLEMENTED
この機能が実装されていない (can_pop_frame 機能が false)

呼び出し側のフレームの取得

jvmdiError
GetCallerFrame(jframeID called, jframeID *framePtr)
frame について、それを呼び出したフレームを、framePtr を使って返します。called (呼び出し先) と呼び出し側の両方のフレームが、Java プログラム言語または JNI メソッド内に存在する必要があります。

パラメータ:

called
呼び出されるフレーム
framePtr
戻ったとき、呼び出し側フレームのフレーム ID をポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_FRAMEID
jframeID が無効

JVMDI_ERROR_NO_MORE_FRAMES
呼び出し側フレームが Java プログラミング言語または JNI メソッド内にない

フレームの位置

jvmdiError
GetFrameLocation(jframeID frame, jclass *classPtr, jmethodID *methodPtr,
                       jlocation *locationPtr)

Java プログラミング言語のフレームについて、現在実行中の命令の位置を返します。

パラメータ:

frame
照会するフレーム
classPtr
戻ったとき、現在の位置のクラスをポイントする。返されるクラスは、JNI グローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある
methodPtr
戻ったとき、現在の位置のメソッドをポイントする
locationPtr
戻ったとき、現在実行中の命令のインデックスをポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_FRAMEID
frame は有効なフレーム ID ではない

フレームのポップの通知

jvmdiError
NotifyFramePop(jframeID frame);
frame がスタックからポップされたとき、JVMDI_EVENT_FRAME_POP イベントを生成します。「イベント」を参照してください。

パラメータ:

frame
フレームのポップイベントが生成されるフレーム

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_FRAMEID
frame は有効なフレーム ID ではない


局所変数のアクセス


局所変数の取得

jvmdiError
GetLocalObject(jframeID frame, jint slot, jobject *valuePtr)
jvmdiError
GetLocalInt(jframeID frame, jint slot, jint *valuePtr)
jvmdiError
GetLocalLong(jframeID frame, jint slot, jlong *valuePtr)
jvmdiError
GetLocalFloat(jframeID frame, jint slot, jfloat *valuePtr)
jvmdiError
GetLocalDouble(jframeID frame, jint slot, jdouble *valuePtr)

これらの関数は、局所変数の値を取得するために使います。GetLocalInt は、int、char、byte、および boolean 型の値の取得に使うことができます。変数は、変数の値を含んでいるフレームと、変数のスロット番号によって識別されます。変数からスロット番号へのマッピングは、関数 GetLocalVariableTable を使って取得できます。

パラメータ:

frame
変数の値を含むフレーム
slot
変数のスロット番号
valuePtr
戻ったとき、変数の値をポイントする。GetLocalObject に関しては、返される値はグローバル参照で、JNI 関数 DeleteGlobalRef() を使って明示的に解放する必要がある

この関数は、次のエラーコードのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_FRAMEID
frame が無効

JVMDI_ERROR_INVALID_SLOT
slot が無効

JVMDI_ERROR_TYPE_MISMATCH
使用した関数と変数の型が合わない

JVMDI_ERROR_OPAQUE_FRAME

局所変数の設定

jvmdiError
SetLocalObject(jframeID frame, jint slot, jobject value)
jvmdiError
SetLocalInt(jframeID frame, jint slot, jint value)
jvmdiError
SetLocalLong(jframeID frame, jint slot, jlong value)
jvmdiError
SetLocalFloat(jframeID frame, jint slot, jfloat value)
jvmdiError
SetLocalDouble(jframeID frame, jint slot, jdouble value)

これらの関数は、局所変数の値を設定するために使います。SetLocalInt は、int、char、byte、および boolean 型の値の設定に使うことができます。変数は、変数の値を含んでいるフレームと、変数のスロット番号によって識別されます。変数からスロット番号へのマッピングは、関数 GetLocalVariableTable を使って取得できます。

パラメータ:

frame
変数の値を含むフレーム
slot
変数のスロット番号
変数の新しい値

この関数は、次のエラーコードのどれかを返します。

JVMDI_ERROR_OPAQUE_FRAME
無効なポインタ

JVMDI_ERROR_INVALID_FRAMEID
frame が無効

JVMDI_ERROR_INVALID_SLOT
slot が無効

JVMDI_ERROR_TYPE_MISMATCH
使用した関数と変数の型が合わない


ブレークポイント


ブレークポイントの設定

jvmdiError
SetBreakpoint(jclass clazz, jmethodID method, jlocation location)

clazzmethod、および location で指定された命令にブレークポイントを設定します。1 つの命令に対して設定できるブレークポイントは 1 つだけです。

指定した命令が実行される直前に、JVMDI_EVENT_BREAKPOINT イベントが生成されます。「イベント」を参照してください。

パラメータ:

clazz
ブレークポイントを設定するクラス
method
ブレークポイントを設定するメソッド
location
ブレークポイントを設定する命令のインデックス

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_INVALID_LOCATION
無効な位置

JVMDI_ERROR_DUPLICATE
指定されたバイトコードにはブレークポイントがすでに設定されている

ブレークポイントの解除

jvmdiError
ClearBreakpoint(jclass clazz, jmethodID method, jlocation location)

clazzmethod、および location で指定されたバイトコードに設定されているブレークポイントを解除します。

パラメータ:

clazz
ブレークポイントを解除するクラス
method
ブレークポイントを解除するメソッド
location
ブレークポイントを解除する命令のインデックス

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_INVALID_LOCATION
無効な位置

JVMDI_ERROR_NOT_FOUND
指定されたバイトコードにはブレークポイントが設定されていない

すべてのブレークポイントの解除

jvmdiError
ClearAllBreakpoints()
この仮想マシンに設定されているブレークポイントをすべて解除します。


監視されるフィールド


フィールドアクセスの監視の設定

jvmdiError
SetFieldAccessWatch(jclass clazz, jfieldID field)

clazz および field で指定されたフィールドがアクセスされようとした時点で、JVMDI_EVENT_FIELD_ACCESS イベントを生成します。イベントは、ClearFieldAccessWatch を使って取り消されるまで、フィールドがアクセスされるたびに生成されます。Java プログラミング言語コードまたは JNI からのフィールドアクセスが監視され、ほかの手段で変更されるフィールドは監視されません。JVMDI のユーザは、自分自身のフィールドアクセスによって監視イベントがトリガされることに注意してください。1 つのフィールドに対し、フィールドアクセスの監視を 1 つだけ設定できます。フィールドの変更はアクセスとはみなされません。変更を監視するには、SetFieldModificationWatch を使います。

この機能はオプションで、すべての仮想マシンに実装しなければならないわけではありません。特定の仮想マシンでサポートされている機能について判別するには、GetCapabilities を使います。

パラメータ:

clazz
監視するフィールドを含むクラス
field
監視するフィールド

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_FIELDID
field に指定された jfieldID が有効なフィールド ID でない

JVMDI_ERROR_INVALID_CLASS
clazz に指定された jclass が有効なクラスでない

JVMDI_ERROR_DUPLICATE
指定されたフィールドはすでにアクセスが監視されている

JVMDI_ERROR_NOT_IMPLEMENTED
このオプション機能は、この VM に存在しない


フィールドアクセスの監視の解除

jvmdiError
ClearFieldAccessWatch(jclass clazz, jfieldID field)

SetFieldAccessWatch を使って設定した、clazz および field で指定されるフィールドに対するフィールドアクセスの監視を取り消します。

パラメータ:

clazz
監視するフィールドを含むクラス
field
監視するフィールド

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_FIELDID
field に指定された jfieldID が有効なフィールド ID でない

JVMDI_ERROR_INVALID_CLASS
clazz に指定された jclass が有効なクラスでない

JVMDI_ERROR_NOT_FOUND
指定されたフィールドはアクセスが監視されていない


フィールド変更の監視の設定

jvmdiError
SetFieldModificationWatch(jclass clazz, jfieldID field)

clazz および field で指定されたフィールドが変更されようとした時点で、JVMDI_EVENT_FIELD_MODIFICATION イベントを生成します。イベントは、ClearFieldModificationWatch を使って取り消されるまで、フィールドが変更されるたびに生成されます。Java プログラミング言語コードまたは JNI からのフィールド変更が監視され、ほかの手段で変更されるフィールドは監視されません。JVMDI のユーザは、自分自身で実行するフィールド変更によって監視イベントがトリガされることに注意してください。1 つのフィールドに対し、フィールド変更の監視を 1 つだけ設定できます。

この機能はオプションで、すべての仮想マシンに実装しなければならないわけではありません。特定の仮想マシンでサポートされている機能について判別するには、GetCapabilities を使います。

パラメータ:

clazz
監視するフィールドを含むクラス
field
監視するフィールド

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_FIELDID
field に指定された jfieldID が有効なフィールド ID でない

JVMDI_ERROR_INVALID_CLASS
clazz に指定された jclass が有効なクラスでない

JVMDI_ERROR_DUPLICATE
指定されたフィールドはすでに変更が監視されている

JVMDI_ERROR_NOT_IMPLEMENTED
このオプション機能は、この VM に存在しない


フィールド変更の監視の解除

jvmdiError
ClearFieldModificationWatch(jclass clazz, jfieldID field)

clazz および field で指定されるフィールドに対して、SetFieldModificationWatch を使って以前に設定したフィールド変更の監視を取り消します。

パラメータ:

clazz
監視するフィールドを含むクラス
field
監視するフィールド

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_FIELDID
field に指定された jfieldID が有効なフィールド ID でない

JVMDI_ERROR_INVALID_CLASS
clazz に指定された jclass が有効なクラスでない

JVMDI_ERROR_NOT_FOUND
指定されたフィールドは変更が監視されていない


クラス情報


クラスのシグニチャー

jvmdiError
GetClassSignature(jclass clazz, char **sigPtr)
clazz で指定されたクラスのクラスのシグニチャーを、sigPtr を使って返します。戻り値は UTF-8 文字列です。

プリミティブクラス (たとえば、java.lang.Integer.TYPE) について返されるシグニチャーは、対応するプリミティブ型のシグニチャー (たとえば、「I」) です。

パラメータ:

clazz
照会するクラス
sigPtr
戻ったとき、クラスのシグニチャー (UTF-8) へのポインタを参照する。返されたシグニチャーの文字列は、Deallocate を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_CLASS
clazz が無効

クラスのステータス

jvmdiError
GetClassStatus(jclass clazz, jint *statusPtr)
クラスのステータスを取得します。次のビットのうち、0 個以上のビットがセットされます。
JVMDI_CLASS_STATUS_VERIFIED
クラスのバイトコードが検証された
JVMDI_CLASS_STATUS_PREPARED
クラスの準備が完了した
JVMDI_CLASS_STATUS_INITIALIZED
クラスの初期化が完了した。静的な初期化子が実行された
JVMDI_CLASS_STATUS_ERROR
初期化中のエラーによりクラスが使用できない

プリミティブクラス (たとえば、java.lang.Integer.TYPE) および配列のステータス値は、未定義です。

パラメータ:

clazz
照会するクラス
statusPtr
戻ったとき、このクラスの現在の状態として上記の 1 つ以上のフラグをポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_CLASS
clazz が無効

ソースファイル名

jvmdiError
GetSourceFileName(jclass clazz, char **sourceNamePtr)
clazz で指定されたクラスについて、sourceNamePtr を介してソースファイル名を返します。返される UTF-8 文字列は、ファイル名だけで、ディレクトリ名は含まれません。

プリミティブクラス (たとえば、java.lang.Integer.TYPE) および配列の場合、この関数は JVMDI_ERROR_ABSENT_INFORMATION を返します。

パラメータ:

clazz
照会するクラス
sourceNamePtr
戻ったとき、クラスのソースファイル名 (UTF-8) へのポインタを参照する。返されるファイル名の文字列は、Deallocate を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_ABSENT_INFORMATION
クラス情報に、ソースパスが含まれていない。これには、クラスが配列クラスまたはプリミティブクラスである場合が含まれる

クラスの修飾子フラグ

jvmdiError
GetClassModifiers(jclass clazz, jint *modifiersPtr)
clazz で指定されたクラスのアクセスフラグを、modifiersPtr を介して返します。アクセスフラグの定義と、クラス修飾子についての情報は、「Java 仮想マシン仕様」を参照してください。

クラスが配列クラスの場合、その public、private および protected 修飾子は、そのコンポーネント型の修飾子と同じです。プリミティブ型の配列の場合、このコンポーネント型は、プリミティブクラスの 1 つ (たとえば、java.lang.Integer.TYPE) で表現されます。

クラスがプリミティブクラスの場合、その public 修飾子は常に true になります。また、その protected 修飾子および private 修飾子は常に false になります。

クラスが配列クラスまたはプリミティブクラスの場合、その final 修飾子は常に true になり、interface 修飾子は常に false になります。その他の修飾子の値は、この仕様では判定されません。

パラメータ:

clazz
照会するクラス
modifiersPtr
戻ったとき、このクラスの現在のアクセスフラグをポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_CLASS
clazz が無効

クラスのメソッド

jvmdiError
GetClassMethods(jclass clazz, jint *methodCountPtr, jmethodID **methodsPtr)
clazz で指定されたクラスに含まれるメソッドの数を methodCountPtr を介して返し、メソッド ID のリストを methodsPtr を介して返します。メソッドのリストには、本来のメソッドだけでなく、コンストラクタおよび static 初期化子も含まれます。直接宣言されたメソッドだけが返されます (継承したメソッドは返されない)。メソッドは、クラスファイル内に出現する順序で返されます。配列クラスおよびプリミティブクラス (たとえば、java.lang.Integer.TYPE) の場合、空のメソッドリストが返されます。

パラメータ:

clazz
照会するクラス
methodCountPtr
戻ったとき、このクラスで宣言されているメソッドの数をポイントする
methodsPtr
戻ったとき、メソッド ID の配列をポイントする。JVMDI アロケータが、配列にメモリを割り当てる。配列は、Deallocate() を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_CLASS_NOT_PREPARED

クラスのフィールド

jvmdiError
GetClassFields(jclass clazz, jint *fieldCountPtr, jfieldID **fieldsPtr)
clazz で指定されたクラスに含まれるフィールドの数を fieldCountPtr を介して返し、フィールド ID のリストを fieldsPtr を介して返します。直接宣言されたフィールドだけが返されます (継承したフィールドは返されない)。フィールドは、クラスファイル内に出現する順序で返されます。配列クラスおよびプリミティブクラス (たとえば、java.lang.Integer.TYPE) の場合、空のフィールドリストが返されます。JNI を使って、配列の長さを判別してください。

パラメータ:

clazz
照会するクラス
fieldCountPtr
戻ったとき、このクラスで宣言されているフィールドの数をポイントする
fieldsPtr
戻ったとき、フィールド ID の配列をポイントする。JVMDI アロケータが、配列にメモリを割り当てる。Deallocate() を使ってメモリを解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_CLASS_NOT_PREPARED

実装されたインタフェース

jvmdiError
GetImplementedInterfaces(jclass clazz,
                       jint *interfaceCountPtr, 
                       jclass **interfacesPtr);
このクラスの直接のスーパーインタフェースを返します。クラスに対しては、この関数は、implements 節で宣言されているインタフェースを返します。インタフェースに対しては、この関数は、extends 節で宣言されているインタフェースを返します。配列クラスおよびプリミティブクラス (たとえば、java.lang.Integer.TYPE) の場合、空のインタフェースリストが返されます。

パラメータ:

clazz
照会するクラス
interfaceCountPtr
戻ったとき、インタフェースの数をポイントする
interfacesPtr
戻ったとき、インタフェースの配列をポイントする。配列内のインタフェースは、JNI グローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある。返されるインタフェースの配列は、Deallocate を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_CLASS_NOT_PREPARED

インタフェースかどうかの検査

jvmdiError
IsInterface(jclass clazz, jboolean *isInterfacePtr)
クラスオブジェクト参照がインタフェースを表しているかどうかを判定します。クラスが実際にインタフェースである場合、jbooleanJNI_TRUE を返し、インタフェースではない場合には JNI_FALSE を返します。

パラメータ:

clazz
照会するクラス
isInterfacePtr
戻ったとき、この関数の boolean 型の結果をポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_CLASS
clazz が無効

配列かどうかの検査

jvmdiError
IsArrayClass(jclass clazz, jboolean *isArrayClassPtr)
クラスオブジェクト参照が配列を表しているかどうかを判定します。jboolean は、クラスが配列である場合は JNI_TRUE になり、そのでない場合は JNI_FALSE になります。

パラメータ:

clazz
照会するクラス
isArrayClassPtr
戻ったとき、この関数の boolean 型の結果をポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_CLASS
clazz が無効

クラスローダ

jvmdiError
GetClassLoader(jclass clazz, jobject *classloaderPtr)
clazz で指定されたクラスのクラスローダへの参照を、classloaderPtr を介して返します。指定したクラスがクラスローダにより作成されたものでない場合には、classloaderPtrnull をポイントします。

パラメータ:

clazz
照会するクラス
classloaderPtr
戻ったとき、このクラスまたはインタフェースをロードしたクラスローダをポイントする。クラスローダを持たない場合は、null をポイントする。返されるクラスローダは、JNI グローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_CLASS
clazz が無効

ソースデバッグ拡張機能

jvmdiError
GetSourceDebugExtension(jclass clazz, char **sourceDebugExtensionPtr)
clazz で指示されたクラスについて、sourceDebugExtensionPtr を介してデバッグ拡張機能を返します。返される UTF-8 文字列には、clazz ファイルに存在するデバッグ拡張情報がそのまま含まれます。

パラメータ:

clazz
照会するクラス
sourceDebugExtensionPtr
戻ったとき、クラスのデバッグ拡張機能名 (UTF-8) へのポインタを参照する。返されたシグニチャーの文字列は、Deallocate を使って解放する必要がある。

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_ABSENT_INFORMATION
クラス情報に、デバッグ拡張が含まれていない


オブジェクト情報


オブジェクトのハッシュコード

jvmdiError
GetObjectHashCode(jobject object, jint *hashCodePtr)
object で指定されたオブジェクトについて、オブジェクト参照のハッシュテーブルの維持に使用できるハッシュコードを、hashCodePtr を介して返します。この関数は、特定のオブジェクトの持続期間中ずっと、そのオブジェクトのハッシュコード値が同じであることを保証します。

パラメータ:

object
照会するオブジェクト
hashCodePtr
戻ったとき、オブジェクトのハッシュコードをポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_OBJECT
object が無効

モニター情報の取得

typedef struct {
    jthread owner;
    jint entry_count;
    jint waiter_count;
    jthread *waiters;
} JVMDI_monitor_info;

jvmdiError
GetMonitorInfo(jobject object, JVMDI_monitor_info *infoPtr)

オブジェクトのモニターに関する情報を取得します。JVMDI_owned_monitor_info 構造体のフィールドに、モニターの詳細が入ります。モニターの状態に影響を与える可能性のある各スレッドは、中断されているか、または現在のスレッドである必要があります。

この機能はオプションで、すべての仮想マシンに実装しなければならないわけではありません。特定の仮想マシンでサポートされている機能について判別するには、GetCapabilities を使います。

パラメータ:

object
照会するオブジェクト
infoPtr
戻ったとき、指定されたオブジェクトのモニター情報が入っている。返されるオブジェクト (所有者、待機者の配列) はグローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある。返される待機者の配列のバッファは、Deallocate を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_OBJECT
thread が無効

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_THREAD_NOT_SUSPENDED
呼び出し前にスレッドが中断されている必要がある

JVMDI_ERROR_NOT_IMPLEMENTED
このオプション機能は、この VM に存在しない


フィールド情報


フィールドの名前とシグニチャー

jvmdiError
GetFieldName(jclass clazz, jfieldID field, 
                   char **namePtr, char **signaturePtr)
clazzfield で指定されたフィールドについて、名前を namePtr で返し、シグニチャーを signaturePtr で返します。

パラメータ:

clazz
照会するクラス
field
照会するフィールド
namePtr
戻ったとき UTF-8 形式のフィールド名へのポインタを参照する。この文字列は、Deallocate を使って解放する必要がある
signaturePtr
戻ったとき、UTF-8 形式のフィールドシグニチャーへのポインタを参照する。この文字列は、Deallocate を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_FIELDID
field が無効

JVMDI_ERROR_INVALID_CLASS
clazz が無効

フィールドの宣言クラス

jvmdiError
GetFieldDeclaringClass(jclass clazz, jfieldID field, jclass *declaringClassPtr)
clazzfield で指定されたフィールドについて、そのフィールドを定義しているクラスを declaringClassPtr を介して返します。宣言しているクラスは、clazz、スーパークラス、または実装されたインタフェースのどれかです。

パラメータ:

clazz
照会するクラス
field
照会するフィールド
declaringClassPtr
戻ったとき、宣言しているクラスをポイントする。返されるクラスは、JNI グローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_FIELDID
field が無効

JVMDI_ERROR_INVALID_CLASS
clazz が無効

フィールドの修飾子フラグ

jvmdiError
GetFieldModifiers(jclass clazz, jfieldID field, jint *modifiersPtr)
clazzfield で指定されたフィールドのアクセスフラグを、modifiersPtr を介して返します。アクセスフラグの定義と、フィールド修飾子についての情報は、「Java 仮想マシン仕様」を参照してください。

パラメータ:

clazz
照会するクラス
field
照会するフィールド
modifiersPtr
戻ったとき、アクセスフラグをポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_FIELDID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

合成フィールドかどうかの検査

jvmdiError
IsFieldSynthetic(jclass clazz, jfieldID field, jboolean *isSyntheticPtr)

clazz および field で指定されたフィールドについて、それが合成フィールドであるかどうかを示す値を、isSyntheticPtr を介して返します。合成フィールドはコンパイラによって生成されますが、元のソースコード内には存在しません。

この機能はオプションで、すべての仮想マシンに実装しなければならないわけではありません。特定の仮想マシンでサポートされている機能について判別するには、GetCapabilities を使います。

パラメータ:

clazz
照会するクラス
field
照会するフィールド
isSyntheticPtr
戻ったとき、この関数の boolean 型の結果をポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_FIELDID
field が無効

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_NOT_IMPLEMENTED
このオプション機能は、この VM に存在しない


メソッド情報


メソッドの名前とシグニチャー

jvmdiError
GetMethodName(jclass clazz, jmethodID method, 
                    char **namePtr, char **signaturePtr)

clazzmethod で指定されたメソッドについて、名前を namePtr で返し、シグニチャーを signaturePtr で返します。このシグニチャーは、JNI シグニチャーで、Java 仮想マシン仕様ではメソッド記述子とも呼ばれています。これは、Java 言語仕様で定義されているメソッドシグニチャーとは違うので、注意してください。

パラメータ:

clazz
照会するクラス
method
照会するメソッド
namePtr
戻ったとき、UTF-8 形式のメソッド名へのポインタを参照する。この文字列は、Deallocate を使って解放する必要がある
signaturePtr
戻ったとき、UTF-8 形式のメソッドシグニチャーへのポインタを参照する。この文字列は、Deallocate を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

メソッドの宣言クラス

jvmdiError
GetMethodDeclaringClass(jclass clazz, jmethodID method,
                                 jclass *declaringClassPtr)
clazzmethod で指定されたメソッドについて、そのメソッドを定義しているクラスを、declaringClassPtr を介して返します。

パラメータ:

clazz
照会するクラス
method
照会するメソッド
declaringClassPtr
戻ったとき、宣言しているクラスをポイントする。返されるクラスは、JNI グローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

メソッドの修飾子フラグ

jvmdiError
GetMethodModifiers(jclass clazz, jmethodID method,
                         jint *modifiersPtr)
clazzmethod で指定されたメソッドのアクセスフラグを、modifiersPtr を介して返します。アクセスフラグの定義と、メソッド修飾子についての情報は、「Java 仮想マシン仕様」を参照してください。

パラメータ:

clazz
照会するクラス
method
照会するメソッド
modifiersPtr
戻ったとき、アクセスフラグをポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

最大スタック

jvmdiError
GetMaxStack(jclass clazz, jmethodID method, jint *maxPtr)
clazzmethod で指定されたメソッドについて、そのメソッドの実行中にスタック上に置ける最大ワード数を、maxPtr を介して返します。

パラメータ:

clazz
照会するクラス
method
照会するメソッド
maxPtr
戻ったとき、スタックの最大ワード数をポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

局所変数のスロット

jvmdiError
GetMaxLocals(jclass clazz, jmethodID method,
                  jint *maxPtr);
clazzmethod で指定されたメソッドについて、そのメソッド全体で使用される局所変数のスロット数を、maxPtr を介して返します。なお、2 ワードの引数は、スロットを 2 つ使用します。

パラメータ:

clazz
照会するクラス
method
照会するメソッド
maxPtr
戻ったとき、局所変数のスロットの最大数をポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

引数のスロット

jvmdiError
GetArgumentsSize(jclass clazz, jmethodID method, jint *sizePtr)
clazzmethod で指定されたメソッドについて、そのメソッドの引数によって使用される局所変数のスロット数を、maxPtr を介して返します。なお、2 ワードの引数は、スロットを 2 つ使用します。

パラメータ:

clazz
照会するクラス
method
照会するメソッド
sizePtr
戻ったとき、引数のスロットの数をポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

ソースの行番号

jvmdiError
GetLineNumberTable(jclass clazz, jmethodID method,
 			 jint *entryCountPtr, 
             JVMDI_line_number_entry **tablePtr)
clazzmethod で指定されたメソッドについて、ソース行番号のエントリから成るテーブルを返します。テーブルのサイズは entryCountPtr により返され、テーブル自体は tablePtr により返されます。テーブルのエントリは、次の構造体のインスタンスです。
typedef struct {
    jlocation start_location;
    jint line_number;
} JVMDI_line_number_entry;
パラメータ:
clazz
照会するクラス
method
照会するメソッド
entryCountPtr
戻ったとき、テーブル内のエントリの数をポイントする
tablePtr
戻ったとき、行番号テーブルのポインタをポイントする。JVMDI アロケータが、テーブルに領域を割り当てる。このテーブルは、Deallocate() を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NONE
エラーなし

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_ABSENT_INFORMATION
クラスの情報に行番号が含まれていない

メソッドの配置位置

jvmdiError
GetMethodLocation(jclass clazz, jmethodID method,
                        jlocation *startLocationPtr, 
                        jlocation *endLocationPtr)
clazzmethod で指定されたメソッドについて、その開始アドレスと終了アドレスを startLocationPtrendLocationPtr により返します。バイトコードの通常のインデックス法では、これらの値は常に、ゼロと、バイトコード数から 1 を引いた数になります。

パラメータ:

clazz
照会するクラス
method
照会するメソッド
startLocationPtr
戻ったとき、最初の位置をポイントする。位置情報が得られない場合は -1 をポイントする
endLocationPtr
戻ったとき、最後の位置をポイントする。位置情報が得られない場合は -1 をポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_ABSENT_INFORMATION
クラス情報にメソッドのサイズが含まれていない

局所変数

jvmdiError
GetLocalVariableTable(jclass clazz, jmethodID method,
                            jint *entryCountPtr, 
                            JVMDI_local_variable_entry **tablePtr)
clazzmethod で指定されたメソッドについて、局所変数のテーブルを返します。テーブルのサイズは entryCountPtr により返され、テーブル自体は tablePtr により返されます。テーブルのエントリは、次の構造体になっています。
typedef struct {
    jlocation start_location;   /* variable valid start_location */
    jint length;                /* up to start_location+length */ 
    char *name;                 /* name in UTF-8 */
    char *signature;            /* type signature in UTF-8 */
    jint slot;                  /* variable slot, see JVMDI_GetLocal*()  */
} JVMDI_local_variable_entry;

パラメータ:

clazz
照会するクラス
method
照会するメソッド
entryCountPtr
戻ったとき、テーブル内のエントリの数をポイントする
tablePtr
戻ったとき、局所変数テーブルのポインタをポイントする。JVMDI アロケータが、テーブルに領域を割り当てる。また、テーブル内のそれぞれの名前およびシグニチャー文字列も、JVMDI アロケータによって割り当てられる。これらのバッファは、Deallocate を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_ABSENT_INFORMATION
クラス情報に局所変数の情報が含まれていない

例外ハンドラ

jvmdiError
GetExceptionHandlerTable(jclass clazz, jmethodID method,
                               jint *entryCountPtr, 
                               JVMDI_exception_handler_entry **tablePtr)
clazzmethod で指定されたメソッドについて、例外ハンドラのテーブルを返します。テーブルのサイズは entryCountPtr により返され、テーブル自体は tablePtr により返されます。テーブルのエントリは、次の構造体になっています。
typedef struct {
    jlocation start_location;
    jlocation end_location;
    jlocation handler_location;
    jclass exception;           /* if null, all exceptions */
} JVMDI_exception_handler_entry;

この関数を呼び出すと、スローされる例外クラスのうち、まだロードされていないクラスのロードが行われることがあります。スレッドの中断中に呼び出してはなりません。

パラメータ:

clazz
照会するクラス
method
照会するメソッド
entryCountPtr
戻ったとき、テーブル内のエントリの数をポイントする
tablePtr
戻ったとき、例外ハンドラテーブルのポインタをポイントする。JVMDI アロケータが、テーブルに領域を割り当てる。このテーブルは、Deallocate() を使って解放する必要があるJVMDI_exception_handler_entry の exception フィールドに返されるクラスは、グローバル参照で、JNI 関数 Deallocate を使って明示的に解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

スローされる例外

jvmdiError
GetThrownExceptions(jclass clazz, jmethodID method,
                          jint *exceptionCountPtr, jclass **exceptionsPtr)
clazzmethod で指定されたメソッドについて、そのメソッドがスローする可能性がある例外クラスの配列を返します。例外の数は、exceptionCountPtr を介して返されます。例外の配列は、exceptionsPtr を介して返されます。

この関数を呼び出すと、スローされる例外クラスのうち、まだロードされていないクラスのロードが行われることがあります。スレッドの中断中に呼び出してはなりません。

パラメータ:

clazz
照会するクラス
method
照会するメソッド
exceptionCountPtr
戻ったとき、スローされる例外の数をポイントする
exceptionsPtr
戻ったとき、スローされる例外への参照 (例外ごとに 1 つずつ) の配列をポイントする。配列内の例外クラスは、JNI グローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある。返される例外の配列は、Deallocate を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
無効な class

バイトコードの取得

jvmdiError
GetBytecodes(jclass clazz, jmethodID method, jint *bytecodeCountPtr,
                         jbyte **bytecodesPtr)
clazzmethod で指定されたメソッドについて、そのメソッドを実装するバイトコードを返します。バイトコードの数は、bytecodeCountPtr を介して返されます。バイトコード自体は、bytecodesPtr を介して返されます。

この機能はオプションで、すべての仮想マシンに実装しなければならないわけではありません。特定の仮想マシンでサポートされている機能について判別するには、GetCapabilities を使います。

パラメータ:

clazz
照会するクラス
method
照会するメソッド
bytecodeCountPtr
戻ったとき、バイトコードの配列の長さをポイントする
bytecodesPtr
戻ったとき、バイトコード配列へのポインタをポイントする。JVMDI のメモリアロケータが、バイトコードの配列にメモリを割り当てる。このテーブルは、Deallocate() を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_NOT_IMPLEMENTED
このオプション機能は、この VM に存在しない

ネイティブメソッドかどうかの検査

jvmdiError
IsMethodNative(jclass clazz, jmethodID method, jboolean *isNativePtr)

clazzmethod で指定されたメソッドがネイティブメソッドかどうかを表す値を、isNativePtr を介して返します。

パラメータ:

clazz
照会するクラス
method
照会するメソッド
isNativePtr
戻ったとき、この関数の boolean 型の結果をポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

合成メソッドかどうかの検査

jvmdiError
IsMethodSynthetic(jclass clazz, jmethodID method, jboolean *isSyntheticPtr)

clazzmethod で指定されたメソッドについて、それが合成メソッドであるかどうかを示す値を、isSyntheticPtr を介して返します。合成メソッドは、コンパイラによって生成されますが、元のソースコード内には存在しません。

この機能はオプションで、すべての仮想マシンに実装しなければならないわけではありません。特定の仮想マシンでサポートされている機能について判別するには、GetCapabilities を使います。

パラメータ:

clazz
照会するクラス
method
照会するメソッド
isSyntheticPtr
戻ったとき、この関数の boolean 型の結果をポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_INVALID_METHODID
無効な method

JVMDI_ERROR_INVALID_CLASS
clazz が無効

JVMDI_ERROR_NOT_IMPLEMENTED
このオプション機能は、この VM に存在しない


raw モニターのサポート


raw モニターの作成

jvmdiError
CreateRawMonitor(char *name, JVMDI_RawMonitor *monitorPtr)
raw モニターを作成します。

パラメータ:

name
モニターを識別する UTF-8 形式の名前
monitorPtr
戻ったとき、作成されたモニターをポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

raw モニターの破棄

jvmdiError
DestroyRawMonitor(JVMDI_RawMonitor monitor)
raw モニターを破棄します。

パラメータ:

monitor
モニター

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_MONITOR
無効なモニター

raw モニターの開始

jvmdiError
RawMonitorEnter(JVMDI_RawMonitor monitor)
raw モニターの排他的所有権を取得します。

パラメータ:

monitor
モニター

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_MONITOR
無効なモニター

raw モニターの終了

jvmdiError
RawMonitorExit(JVMDI_RawMonitor monitor)
raw モニターの排他的所有権を解放します。

パラメータ:

monitor
モニター

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_MONITOR
無効なモニター

JVMDI_ERROR_NOT_MONITOR_OWNER

raw モニターの待機

jvmdiError
RawMonitorWait(JVMDI_RawMonitor monitor, jlong millis)
raw モニターの通知を待ちます。

パラメータ:

monitor
モニター
millis
タイムアウト (ミリ秒単位)

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_MONITOR
無効なモニター

JVMDI_ERROR_NOT_MONITOR_OWNER

JVMDI_ERROR_INTERRUPT

raw モニターの通知

jvmdiError
RawMonitorNotify(JVMDI_RawMonitor monitor)
raw モニターを待機中の 1 つのスレッドに通知します。

パラメータ:

monitor
モニター

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_MONITOR
無効なモニター

JVMDI_ERROR_NOT_MONITOR_OWNER

raw モニターの通知 (すべて)

jvmdiError
RawMonitorNotifyAll(JVMDI_RawMonitor monitor)
raw モニターを待機中のすべてのスレッドに通知します。

パラメータ:

monitor
モニター

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_MONITOR
無効なモニター

JVMDI_ERROR_NOT_MONITOR_OWNER


イベント


イベントフックの設定

typedef void (*JVMDI_EventHook)(JNIEnv *env , JVMDI_Event *event);

jvmdiError
SetEventHook(JVMDI_EventHook hook)
すべてのイベントごとに呼び出される関数を設定します。イベントの詳細は、このドキュメントで後述します。

パラメータ:

hook
新しいイベントフック、または null (既存のフックを削除する場合)

この関数は、エラーの場合は汎用エラーを返します。


イベントの有効化と無効化

jvmdiError
SetEventNotificationMode(jint mode, jint eventType, jthread thread, ...)
イベントの生成を制御します。mode が JVMDI_ENABLE の場合は、イベント eventType が有効にされます。mode が JVMDI_DISABLE の場合は、イベントが無効にされます。thread が null の場合は、このイベントはグローバルに有効または無効にされます。そうでない場合は、特定のスレッドについて有効または無効にされます。特定のスレッドについてイベントが生成されるのは、イベントがスレッドレベルまたはグローバルレベルのどちらかで有効にされている場合です。

イベントの有効化は、グローバルとスレッド単位でそれぞれ独立しています。たとえば、MethodEntry が最初にグローバルでも各スレッドでも無効になっている場合、MethodEntry をグローバルで有効にしても、スレッド単位では無効のままです。実行中のスレッドが潜在的なイベント条件に遭遇した場合、そのイベントがグローバルまたは実行中のスレッドで有効にされていると、そのイベントが送られます。イベントのグローバルな有効化は、呼び出しの後に作成されるスレッドにも適用されます。

個々のイベントについての情報は、後述する説明を参照してください。

次のイベントは、この関数を使ってスレッドレベルでは制御 (有効化または無効化) できません。

次のイベントは、この関数を使ってグローバルレベルでは制御 (有効化または無効化) できません。

最初は、スレッドレベルで有効にされているイベントはありません。次のイベント以外のイベントが、グローバルレベルで有効にされています。

すべてのイベントごとに呼び出される関数を設定します。イベントの詳細は、このドキュメントで後述します。

パラメータ:

mode
JVMDI_ENABLE または JVMDI_DISABLE
eventType
制御するイベント
thread
制御するスレッド、または null (すべてのスレッドの場合)

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_THREAD
thread が無効、または実行されていない場合

JVMDI_ERROR_INVALID_EVENT_TYPE
eventType が無効な値の場合

JVMDI_ERROR_ILLEGAL_ARGUMENT
thread 引数が、次のいずれかのイベントと一緒に指定されている場合
  • JVMDI_EVENT_VM_INIT
  • JVMDI_EVENT_VM_DEATH
  • JVMDI_EVENT_THREAD_START
  • JVMDI_EVENT_CLASS_UNLOAD


その他の関数


ロード済みクラスの取得

jvmdiError
GetLoadedClasses(jint *classCountPtr, jclass **classesPtr)

仮想マシンにロードされている全クラスの配列を返します。配列内のクラスの数は classCountPtr によって返され、配列自体は classesPtr によって返されます。配列は、Deallocate() を使って解放する必要があります。

返されるリストには、すべての型の配列クラス (プリミティブ型の配列を含む) が含まれます。プリミティブクラス (たとえば、java.lang.Integer.TYPE) は、このリストには含まれません。

パラメータ:

classCountPtr
戻ったとき、クラスの数をポイントする
classesPtr
戻ったとき、各クラスへの参照 (クラスごとに 1 つずつ) の配列をポイントする。配列内のクラスは、JNI グローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある。返されるクラス配列は、Deallocate を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

クラスローダクラスの取得

jvmdiError
GetClassLoaderClasses(jobject initiatingLoader, jint *classCountPtr, jclass **classesPtr)

このクラスローダが起動ローダとして記録されている、すべてのクラスの配列を返します。返される配列内の各クラスは、このクラスローダによって直接定義されて作成されたものか、または別のクラスローダに委譲して作成されたものです。

JDK 1.1 の実装では、起動クラスローダと定義クラスローダの区別が認識されないため、この関数は、仮想マシンにロードされたすべてのクラスを返します。配列内のクラスの数は classCountPtr によって返され、配列自体は classesPtr によって返されます。配列は、Deallocate() を使って解放する必要があります。

initiatingLoader 引数は、null であってはなりません。システムクラスローダにより起動されたクラスのセットは、そのローダにより定義されたクラスのセットと同一です。このセットを判別するには、GetLoadedClasses を呼び出して、クラスローダが null のクラスを選び出します。

パラメータ:

initiatingLoader
起動クラスローダ
classCountPtr
戻ったとき、クラスの数をポイントする
classesPtr
戻ったとき、各クラスへの参照 (クラスごとに 1 つずつ) の配列をポイントする。配列内のクラスは、JNI グローバル参照で、JNI 関数 DeleteGlobalRef を使って明示的に解放する必要がある。返されるクラス配列は、Deallocate を使って解放する必要がある

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

クラスの再定義

typedef struct {
    jclass clazz;              /* Class to be redefined */
    jint class_byte_count;     /* number of bytes defining class (below) */
    jbyte *class_bytes;        /* bytes defining class */
                               /* (in Class File Format of JVM spec) */
} JVMDI_class_definition;

jvmdiError
RedefineClasses(jint classCount, JVMDI_class_definition *classDefs)

指定されたクラスはすべて、提供される定義に従って再定義されます。再定義されたメソッドにアクティブなスタックフレームがあると、そのアクティブフレームは元のメソッドのバイトコードの実行を続行します。再定義したメソッドは、新しい呼び出しで使用されます。jmethodID を返す JVMDI の関数またはイベントは、再定義したメソッド (下記参照) と同等でないかぎり、元のメソッドを参照するときに OBSOLETE_METHOD_ID を返します。たとえば、元のメソッドがまだ実行しているスタックフレームを検査するときなどです。元のメソッド ID は再定義されたメソッドを参照します。JVMDI クライアントで OBSOLETE_METHOD_ID を扱う際には注意が必要です。スタックフレームをリセットする場合は、OBSOLETE_METHOD_ID とともに PopFrame を使用し、フレームをポップしてください。

元のメソッドと再定義したメソッドが同等とみなされるのは、次のような場合です。

この関数により、一般的な JVM セマンティクスのもとで行われる以外の初期化は起こりません。つまり、クラスを再定義しても、そのクラスの初期化は実行されません。既存のスタティック変数は、呼び出し前の状態のままです。ただし、まったく初期化されていない (新しい) スタティック変数には、既定値が割り当てられます。

再定義したクラスにインスタンスがある場合、そのインスタンスのフィールドは呼び出し完了時に再定義したクラスで定義されます。既存のフィールドは以前の値を保持します。新しいフィールドは既定値となります。インスタンスイニシャライザやコンストラクタは実行しません。

スレッドを中断する必要はありません。

クラス内のブレークポイントは解除されます。

属性はすべて更新されます。

この関数は、JVMDI イベントを生成しません。

この機能はオプションで、すべての仮想マシンに実装しなければならないわけではありません。特定の仮想マシンでこの機能がサポートされているかどうかを判定するには、GetCapabilitiescan_redefine_classedcan_add_method および can_unrestrictedly_redefine_classes を調べてください。

パラメータ:

classCount
classDefs で指定されたクラスの数
classDefs
新しいクラス定義の配列数
この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ。classDefs または class_bytes の 1 つが null

JVMDI_ERROR_INVALID_CLASS
ClassDefs の要素が有効なクラスではない

JVMDI_ERROR_UNSUPPORTED_VERSION
新しいクラスファイルのバージョンがこの VM でサポートされていない

JVMDI_ERROR_INVALID_CLASS_FORMAT
新しいクラスファイルの形式が正しくない (VM がClassFormatError を返す)

JVMDI_ERROR_CIRCULAR_CLASS_DEFINITION
新しいクラスファイルの定義が循環定義になる (VM は ClassCircularityError を返す)

JVMDI_ERROR_FAILS_VERIFICATION
クラスバイトが検証に失敗する

JVMDI_ERROR_NAMES_DONT_MATCH
新しいクラスファイル内で定義されたクラス名が、旧クラスオブジェクト内の名前と異なる

JVMDI_ERROR_NOT_IMPLEMENTED
この機能は実装されていない (can_redefine_classes 機能が false)

JVMDI_ERROR_ADD_METHOD_NOT_IMPLEMENTED
新しいクラスファイルでメソッドの追加が必要になる (can_add_method 機能が false)

JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED
新しいクラスのバージョンによりフィールドが変更される (can_unrestrictedly_redefine_classes が false)

JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED
新しいクラスのバージョンの直接スーパークラスが異なる、または直接実装されているインタフェースが異なる (can_unrestrictedly_redefine_classes が false)

JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED
新しいクラスのバージョンでは旧クラスのバージョンで宣言したメソッドを宣言しない(can_unrestrictedly_redefine_classes が false)

JVMDI_ERROR_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED
クラスの新しいバージョンのクラス修飾子 (public、abstract、final など) が旧バージョンと異なる (can_unrestrictedly_redefine_classes が false)

JVMDI_ERROR_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED
クラスの新しいバージョンのメソッド修飾子 (public、abstract、final など) が旧バージョンと異なる (can_unrestrictedly_redefine_classes が false)

バージョン番号の取得

jvmdiError
GetVersionNumber(jint *versionPtr)
JVMDI のバージョンを、versionPtr を介して返します。戻り値はバージョン識別子です。下位の 16 ビットは、マイナーバージョン番号を表します。次の 12 ビットは、メジャーバージョン番号を表します。上位の 4 ビットは、未定義です。

パラメータ:

versionPtr
戻ったとき、JVMDI のバージョンをポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ

機能の取得

typedef struct {
    unsigned int can_watch_field_modification        : 1;
    unsigned int can_watch_field_access              : 1;
    unsigned int can_get_bytecodes                   : 1;
    unsigned int can_get_synthetic_attribute         : 1;
    unsigned int can_get_owned_monitor_info          : 1;
    unsigned int can_get_current_contended_monitor   : 1;
    unsigned int can_get_monitor_info                : 1;
    unsigned int reserved1                           : 1;
    unsigned int reserved2                           : 1;
    unsigned int reserved3                           : 1;
    unsigned int can_pop_frame                       : 1;
    unsigned int reserved4                           : 1;
    unsigned int can_redefine_classes                : 1; 
    unsigned int can_add_method                      : 1;
    unsigned int can_unrestrictedly_redefine_classes : 1;
    unsigned int reserved5                           : 1;
} JVMDI_capabilities;

jvmdiError
GetCapabilities(JVMDI_capabilities *capabilitiesPtr)
capabilitiesPtr を介して、この実装でサポートされているオプションの JVMDI 機能を返します。capabilities 構造体には、フラグ名に示されている機能がサポートされているかどうかを示す、いくつかの boolean 型のフラグが含まれています。

パラメータ:

capabilitiesPtr
戻ったとき、JVMDI の機能をポイントする

この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_NULL_POINTER
無効なポインタ


エラー

JVMDI 関数はすべて、jvmdiError エラーコードを返します。

汎用エラー

以下は、すべての JVMDI 関数によって返される可能性があるエラーです。これらのエラーは、個々の関数の説明に含まれていません。

JVMDI_ERROR_NONE
エラーは発生しなかった。関数の実行が正常に終了したときに返されるエラーコード

JVMDI_ERROR_OUT_OF_MEMORY
関数でメモリの割り当てが必要になったが、これ以上割り当てられるメモリがなかった

JVMDI_ERROR_ACCESS_DENIED
この仮想マシンではデバッグが有効になっていない。JVMDI が使用できない

JVMDI_ERROR_UNATTACHED_THREAD
この関数の呼び出しに使われているスレッドが、仮想マシンに接続されていない。呼び出しは、接続されたスレッドから行う必要がある。JNI 呼び出し API の AttachCurrentThread() を参照

JVMDI_ERROR_VM_DEAD
仮想マシンが動作していない

JVMDI_ERROR_INTERNAL
予期しない内部エラーが発生した

個々の関数に特有のエラー

以下は、一部の JVMDI 関数によって返されるエラーです。これらのエラーは、個々の関数の説明に含まれています。

JVMDI_ERROR_INVALID_THREAD
渡されたスレッドが null、無効、またはすでに終了している

JVMDI_ERROR_INVALID_FIELDID
無効なフィールド

JVMDI_ERROR_INVALID_METHODID
無効なメソッド

JVMDI_ERROR_INVALID_LOCATION
無効な位置

JVMDI_ERROR_INVALID_FRAMEID
無効な jframeID

JVMDI_ERROR_NO_MORE_FRAMES
呼び出しスタックに Java または JNI フレームがなくなった

JVMDI_ERROR_OPAQUE_FRAME
フレームの情報が入手できない (たとえば、ネイティブフレームの場合)

JVMDI_ERROR_NOT_CURRENT_FRAME
操作は現在のフレームでしか実行できない

JVMDI_ERROR_TYPE_MISMATCH
変数の型が、使用される関数に対して適切でない

JVMDI_ERROR_INVALID_SLOT
無効なスロット

JVMDI_ERROR_DUPLICATE
すでに設定された項目

JVMDI_ERROR_THREAD_NOT_SUSPENDED
スレッドが中断されていない

JVMDI_ERROR_THREAD_SUSPENDED
スレッドがすでに中断されている

JVMDI_ERROR_INVALID_OBJECT
無効なオブジェクト

JVMDI_ERROR_INVALID_CLASS
無効なクラス

JVMDI_ERROR_CLASS_NOT_PREPARED
クラスがロードされているが、まだ準備されていない

JVMDI_ERROR_NULL_POINTER
無効なポインタ

JVMDI_ERROR_ABSENT_INFORMATION
要求された情報が入手できない

JVMDI_ERROR_INVALID_EVENT_TYPE
指定されたイベント型の ID が認識されない

JVMDI_ERROR_NOT_IMPLEMENTED
この機能は、この仮想マシンには実装されていない

JVMDI_ERROR_INVALID_THREAD_GROUP
スレッドグループが無効

JVMDI_ERROR_INVALID_PRIORITY
無効な優先順位

JVMDI_ERROR_NOT_FOUND
目的の要素 (フィールドやブレークポイントなど) が見つからない

JVMDI_ERROR_INVALID_MONITOR
無効なモニター

JVMDI_ERROR_ILLEGAL_ARGUMENT
不正な引数

JVMDI_ERROR_NOT_MONITOR_OWNER
このスレッドはモニターを所有していない

JVMDI_ERROR_ABSENT_INFORMATION
目的の情報を入手できない

JVMDI_ERROR_INTERRUPT
呼び出しの完了前に割り込まれた

JVMDI_ERROR_INVALID_TYPESTATE
スレッドの状態が変更されたため、不整合が生じている

JVMDI_ERROR_UNSUPPORTED_VERSION
新しいクラスファイルのバージョンがこの VM でサポートされていない

JVMDI_ERROR_INVALID_CLASS_FORMAT
新しいクラスファイルの形式が正しくない (VM がClassFormatError を返す)

JVMDI_ERROR_CIRCULAR_CLASS_DEFINITION
新しいクラスファイルの定義が循環定義になる (VM は ClassCircularityError を返す)

JVMDI_ERROR_ADD_METHOD_NOT_IMPLEMENTED
新しいクラスファイルでメソッドの追加が必要になり、can_add_method 機能が false

JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED
新しいクラスファイルではスキーマの変更が必要になり、can_unrestrictedly_redefine_classes が false

JVMDI_ERROR_FAILS_VERIFICATION
クラスバイトが検証に失敗する

JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED
新しいクラスのバージョンの直接スーパークラスが異なる、または直接実装されているインタフェースが異なり、can_unrestrictedly_redefine_classes が false

JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED
新しいクラスのバージョンでは、旧クラスのバージョンで宣言したメソッドを宣言せず、また can_unrestrictedly_redefine_classes が false

JVMDI_ERROR_NAMES_DONT_MATCH
新しいクラスファイル内で定義されたクラス名が、旧クラスオブジェクト内の名前と異なる

JVMDI_ERROR_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED
クラスの新しいバージョンのクラス修飾子 (public、abstract、final など) が旧バージョンと異なる (can_unrestrictedly_redefine_classes が false)

JVMDI_ERROR_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED
クラスの新しいバージョンのメソッド修飾子 (public、abstract、final など) が旧バージョンと異なる (can_unrestrictedly_redefine_classes が false)


イベントの処理

JVMDI のクライアントは、アプリケーションプログラム内で発生する多くのイベントについての通知を受けることができます。

イベントを処理するには、SetEventHook を使ってフック関数を指定します。各イベントに対して、イベント型とその他の情報 (一部のイベントの場合) を記述した JVMDI_Event 引数を指定して、そのフック関数が呼び出されます。フック関数は、通常、アプリケーションスレッド内から呼び出されます。JVMDI 実装は、どんな形でもイベントをキューに入れません。これは、イベントのフック関数を注意深く記述する必要があることを意味しています。このあと、一般的なガイドラインを説明します。さらに詳しい提案については、個々のイベントの説明を参照してください。

JVMDI イベントの中には、JNI 参照を使ってオブジェクトを識別するものがあります。そのような参照はすべて、JVMDI_Event 引数を介してイベントフック関数に渡されます。JVMDI イベント内のすべての参照は、JNI ローカル参照で、イベントフック関数から復帰すると無効になります。 JVMDI_Event データ構造体は、ローカルに割り当てられ、イベントフック関数から復帰すると解放されます。

イベントは、関数 SetEventNotificationMode を使って有効および無効にできます。アプリケーションの起動時に有効にされているイベントと、そうでないイベントがあります。この関数の詳細は、ドキュメントを参照してください。

イベントを生成するスレッドの実行状態は変化しません。スレッドを中断させる必要のあるイベントの場合は、イベントフック関数の中で SuspendThread を使って明示的にスレッドを中断させなければなりません。

JVMDI_Event には、イベントの種類と、さらに多くの情報を含むイベント固有の構造体の共用体が含まれます。

typedef struct {
    jint kind;		/* the discriminant */

    union {
	/* kind = JVMDI_EVENT_SINGLE_STEP */
        JVMDI_single_step_event_data single_step;
			
        /* kind = JVMDI_EVENT_BREAKPOINT */
        JVMDI_breakpoint_event_data breakpoint;

        /* kind = JVMDI_EVENT_FRAME_POP */
        /* kind = JVMDI_EVENT_METHOD_ENTRY */
        /* kind = JVMDI_EVENT_METHOD_EXIT */
        JVMDI_frame_event_data frame;

        /* kind = JVMDI_EVENT_FIELD_ACCESS */
        JVMDI_field_access_event_data field_access;

        /* kind = JVMDI_EVENT_FIELD_MODIFICATION */
        JVMDI_field_modification_event_data field_modification;

        /* kind = JVMDI_EVENT_EXCEPTION */
        JVMDI_exception_event_data exception;

        /* kind = JVMDI_EVENT_EXCEPTION_CATCH */
        JVMDI_exception_catch_event_data exception_catch;

        /* kind = JVMDI_EVENT_USER_DEFINED */
        JVMDI_user_event_data user;
			
        /* kind = JVMDI_EVENT_THREAD_END or */
        /* JVMDI_EVENT_THREAD_START */
        JVMDI_thread_change_event_data thread_change;
			
        /* kind = JVMDI_EVENT_CLASS_LOAD, */
        /* JVMDI_EVENT_CLASS_UNLOAD, or */
        /* JVMDI_EVENT_CLASS_PREPARE */
        JVMDI_class_event_data class_event;
			
        /* kind = JVMDI_EVENT_VM_DEATH, JVMDI_EVENT_VM_INIT */
        /* no additional fields */		
    } u;
} JVMDI_Event;

個々のイベントの詳細について、このあと説明します。


ステップ実行イベント (JVMDI_EVENT_SINGLE_STEP)

    typedef struct { 
        jthread thread;
        jclass clazz;
        jmethodID method;
        jlocation location;
    } JVMDI_single_step_event_data;

ステップ実行イベントを利用すると、JVMDI クライアントは、VM で可能な最小の単位でスレッドの実行を追跡できます。ステップ実行イベントは、スレッドが新しい位置に達するたびに生成されます。通常、ステップ実行イベントは、仮想マシンの仕様に定義されている VM の命令の 1 つが完了したことを表します。しかし、実装によっては、位置の定義方法が異なる場合があります。いずれにしても、イベント構造体の clazzmethod、および location フィールドによって現在の位置を一意に識別できるため、この情報があればソースファイルと行番号へのマッピングが可能です。

ネイティブメソッド内からは、ステップ実行イベントは生成されません。

ステップ実行イベントは、デフォルトでは無効になっています。SetEventNotificationMode を呼び出すことにより、スレッドに対して有効にできます。


ブレークポイントイベント (JVMDI_EVENT_BREAKPOINT)

    typedef struct { 
        jthread thread;
        jclass clazz;
        jmethodID method;
        jlocation location;
    } JVMDI_breakpoint_event_data;

ブレークポイントイベントは、SetBreakpoint を使ってブレークポイントとして指定された位置にスレッドが達した時点で生成されます。イベント構造体の clazzmethod、および location フィールドによって現在の位置を一意に識別できるため、この情報があればソースファイルと行番号へのマッピングが可能です。

ブレークポイントのレポートは、通常は SetEventNotificationMode の呼び出しによって有効または無効にできます。デフォルトでは、有効になっています。無効になっている場合、設定されているブレークポイントは無視されます。


フィールドイベント (JVMDI_EVENT_FIELD_ACCESS、JVMDI_EVENT_FIELD_MODIFICATION)

    /* kind = JVMDI_EVENT_FIELD_ACCESS */
    typedef struct { 
        jthread thread;
        jclass clazz;
        jmethodID method;
        jlocation location;
        jclass field_clazz;
        jobject object;
        jfieldID field;
    } JVMDI_field_access_event_data;
    
    /* kind = JVMDI_EVENT_FIELD_MODIFICATION */
    typedef struct { 
        jthread thread;
        jclass clazz;
        jmethodID method;
        jlocation location;
        jclass field_clazz;
        jobject object;
        jfieldID field;
        char signature_type;
        jvalue new_value;
    } JVMDI_field_modification_event_data;

フィールドイベントは、SetFieldAccessWatch または SetFieldModificationWatch を使ってウォッチポイントとして指定されたフィールドを、スレッドがアクセスまたは変更した時点で生成されます。イベント構造体の clazzmethod、および location フィールドは現在の位置を一意に識別するため、この情報があればソースファイルと行番号へのマッピングが可能です。field_clazz および field フィールドは、アクセスまたは変更されるフィールドを一意に識別します。object は、フィールドがインスタンスフィールドである場合に、そのフィールドを含んでいるオブジェクトを識別します。そうでない場合は、null です。

フィールドウォッチポイントのレポートは、通常、SetEventNotificationMode の呼び出しによって有効または無効にできます。デフォルトでは、有効になっています。無効になっている場合、設定されているウォッチポイントは無視されます。


フレームイベント (JVMDI_EVENT_FRAME_POP、JVMDI_EVENT_METHOD_ENTRY、JVMDI_EVENT_METHOD_EXIT)

    typedef struct { 
        jthread thread;
        jclass clazz;
        jmethodID method;
        jframeID frame;
    } JVMDI_frame_event_data;

メソッドエントリイベントは、Java プログラミング言語メソッドまたはネイティブメソッドに入る時点で生成されます。メソッド終了イベントは、Java プログラミング言語メソッドまたはネイティブメソッドから出る時点で生成されます。フレームポップイベントは、NotifyFramePop の呼び出しで指定された単一のフレーム内の単一のメソッドから出る時点で生成されます呼び出し側に例外をスローしてメソッドが終了する場合は、メソッド終了イベントもフレームポップイベントも生成されません。JVMDI クライアントは、そのような事態の発生を、例外キャッチイベントを監視することによって確認できます。

clazz および method フィールドは、入るメソッドまたは出るメソッドを一意に識別します。frame フィールドは、メソッドのスタックフレームへのアクセスを提供します。メソッドに入る時点で、GetFrameLocation によりレポートされる位置は、メソッド内の初期実行可能ファイルの位置を識別します。メソッドを出る時点、またはフレームポップの時点で、GetFrameLocation によりレポートされる位置は、復帰しようとしているメソッド内の復帰直前の実行可能位置を識別します。

メソッドエントリおよびメソッド終了イベントは、デフォルトでは無効になっており、SetEventNotificationMode を呼び出すことによって有効にできます。フレームポップイベントは、デフォルトでは有効になっており、同様の呼び出しで無効にできます。


例外イベント (JVMDI_EVENT_EXCEPTION)

    typedef struct { 
        jthread thread;
        jclass clazz;
        jmethodID method;
        jlocation location;
        jobject exception;
        jclass catch_clazz;
        jmethodID catch_method;
        jlocation catch_location;
    } JVMDI_exception_event_data;

例外イベントは、Java プログラミング言語メソッド内で例外が最初に検出された時点で生成されます。例外は、Java プログラミング言語メソッドによってスローされる場合と、ネイティブメソッドによってスローされる場合があります。ネイティブメソッドによってスローされる場合は、その例外が Java プログラミング言語メソッドによって最初に認識されるまで、このイベントは生成されません。例外がネイティブメソッド内で生成されて解除された場合 (つまり、Java プログラミング言語コードからは認識されない場合) は、例外イベントは生成されません。

イベント構造体の clazzmethod、および location フィールドにより、例外が検出された現在位置を一意に識別できるため、この情報があればソースファイルと行番号へのマッピングが可能です。exception フィールドは、スローされた例外オブジェクトを認識します。catch_clazzcatch_method、および catch_location は、スローされた例外を処理する catch 節の位置を識別します (そのような節が存在する場合)。そのような catch 節がない場合、それらの各フィールドは 0 に設定されます。スレッドがこの catch 節に到達するという保証はありません。呼び出しスタック上で例外スローの位置と catch 節の間にネイティブメソッドがある場合、それらのネイティブメソッドのどれかによって例外がリセットされる可能性があるからです。JVMDI クライアントは、そのような事態の発生を、例外キャッチイベントを監視することによって確認できます。

例外イベントはデフォルトでは有効になっており、SetEventNotificationMode を呼び出すことによって無効にできます。


例外キャッチイベント (JVMDI_EVENT_EXCEPTION_CATCH)

    typedef struct { 
        jthread thread;
        jclass clazz;
        jmethodID method;
        jlocation location;
        jobject exception;
    } JVMDI_exception_catch_event_data;

例外キャッチイベントは、スローされた例外がキャッチされた時点で生成されます。例外が Java プログラミング言語メソッド内でキャッチされた場合は、catch 節に到達した時点でこのイベントが生成されます。例外がネイティブメソッド内でキャッチされた場合は、Java プログラミング言語メソッドに制御が戻った直後にこのイベントが生成されます。例外キャッチイベントは、Java プログラミング言語メソッド内でスローが検出された例外に対して生成されます。

イベント構造体の clazzmethod、および location フィールドによって現在の位置を一意に識別できるため、この情報があればソースファイルと行番号へのマッピングが可能です。Java プログラミング言語メソッド内でキャッチされた例外の場合は、exception オブジェクトが例外オブジェクトを識別します。ネイティブメソッド内でキャッチされた例外は、例外のキャッチがレポートされた時点で入手可能とは限らないので、exception フィールドは null に設定されます。

例外キャッチイベントは、デフォルトでは無効になっており、SetEventNotificationMode を呼び出すことによって有効にできます。


ユーザ定義イベント (JVMDI_EVENT_USER_DEFINED)

    typedef struct { 
        jobject object;
        jint key;
    } JVMDI_user_event_data;

ユーザイベントのデータ構造体にあるユーザ定義イベントおよびフィールドの意味は、JVMDI の個々の実装によって定義されます。


スレッドイベント (JVMDI_EVENT_THREAD_END、JVMDI_EVENT_THREAD_START)

    typedef struct { 
        jthread thread;
    } JVMDI_thread_change_event_data;

スレッド開始イベントは、新しいスレッドによって、スレッドの初期メソッドが実行される前に、生成されます。スレッド終了イベントは、停止しようとしているスレッドによって、スレッドの初期メソッドの実行完了後に、生成されます。スレッド開始イベントが生成される前、およびスレッド終了イベントが生成されたあとに、GetAllThreads によって返される配列に、そのスレッドが含まれている可能性があります。また、スレッド開始イベントの前に、そのスレッドについて他のイベントが生成される可能性があります。しかし、スレッド終了イベントの後に、そのスレッドについて他のイベントが生成されることはありません。

スレッドイベントは、デフォルトでは有効になっており、SetEventNotificationMode を呼び出すことによって無効にできます。


クラスイベント (JVMDI_EVENT_CLASS_LOAD、JVMDI_EVENT_CLASS_UNLOAD、JVMDI_EVENT_CLASS_PREPARE)

    typedef struct { 
        jthread thread;
        jclass clazz;
    } JVMDI_class_event_data;

クラスイベントは、特定のクラスのステータスが変化したことを示します。

クラスロードイベントは、クラスが最初にロードされた時点で生成されます。特定のスレッドによりクラスロードイベントが生成される順序は、そのスレッド内でクラスがロードされる順序と一致することが保証されています。非プリミティブ型の配列には、クラスロードイベントがあります。プリミティブ型の配列には、クラスロードイベントがありません (VM の初期化の時点でロードされたと見なされる)。プリミティブクラス (たとえば、java.lang.Integer.TYPE) には、クラスロードイベントがありません。

クラス準備イベントは、クラスの準備が完了した時点で生成されます。この時点では、クラスのフィールド、メソッド、および実装されたインタフェースが利用可能ですが、クラスのコードはまだ何も実行されていません。配列クラスは、フィールドやメソッドを持つことがないため、配列クラスについてクラス準備イベントが生成されることはありません。プリミティブクラス (たとえば、java.lang.Integer.TYPE) についても、クラス準備イベントは生成されません。

クラスアンロードイベントは、クラスがアンロードされる直前に生成されます。クラスアンロードイベントはガベージコレクション中に発生するため、特に慎重に処理しなければなりません。ガベージコレクタが多くのロックを保持し、ほかのスレッドをすべて中断しているので、イベントハンドラはロックを獲得する機能を使えないかもしれません。クラスアンロードのイベントハンドラでは、あとで処理するべき情報をキューに入れるなどして、処理をできるだけ行わないようにする必要があります。

クラスイベントは、デフォルトでは有効になっており、SetEventNotificationMode を呼び出すことによって無効にできます。


VM 初期化イベント (JVMDI_EVENT_VM_INIT)

VM 初期化イベントは、VM の初期化の完了を示します。このイベントが生成されたあとは、JVMDI クライアントは任意の JNI または JVMDI 関数を自由に呼び出すことができます。VM 初期化イベントは、その前に他のイベントが生成されたり、他のイベントと同時に生成されたりすることがあります。そのうち、VM 初期化イベントの前の生成されるイベントについては、VM の初期化がまだ完了していないので、特に注意して処理する必要があります。メインアプリケーションスレッドのスレッド開始イベントは、VM 初期化イベントのハンドラが復帰するまでは発生しないことが保証されています。


VM 終了イベント (JVMDI_EVENT_VM_DEATH)

VM 終了イベントは、VM の終了を JVMDI クライアントに通知します。

同じ位置で発生する複数のイベント

多くの状況で、1 つのスレッド内の同じ位置で複数のイベントが発生する可能性があります。そのような状況では、このあとに説明する順序で、イベントフックによりすべてのイベントがレポートされます。

現在位置がメソッドのエントリポイントである場合は、同一スレッド内の現在位置で発生した他のすべてのイベントより前に、JVMDI_EVENT_METHOD_ENTRY イベントがレポートされます。

現在位置で例外のキャッチが検出された場合 (catch 節の先頭の場合か、未処理の例外を解除したネイティブメソッドが復帰した位置の場合) は、同一スレッド内の現在位置で発生した他のすべてのイベントより前に、JVMDI_EVENT_EXCEPTION_CATCH イベントがレポートされます。

JVMDI_EVENT_SINGLE_STEP イベントまたは JVMDI_EVENT_BREAKPOINT イベントが現在位置でトリガされる場合、そのイベントは、現在位置のコードが実行される直前に発生するものと定義されています。これらのイベントは、同一スレッド内の現在位置にあるコードの実行によりトリガされるどのイベント (特に、JVMDI_EVENT_EXCEPTIONJVMDI_EVENT_FIELD_ACCESS、および JVMDI_EVENT_FIELD_MODIFICATION) よりも前にレポートされます。ステップイベントとブレークポイントイベントの両方が同一のスレッドおよび場所でトリガされた場合は、ステップイベントがブレークポイントイベントより前にレポートされます。

現在位置がメソッドの終了ポイント (つまり、呼び出し側に復帰する前の最後の位置) である場合、 JVMDI_EVENT_METHOD_EXIT イベントおよび JVMDI_EVENT_FRAME_POP イベント (要求されている場合) は、同一スレッド内の現在位置で発生する他のすべてのイベントのあとにレポートされます。これら 2 つのイベントについては、レポートされる順序は特に指定されていません。

同じ位置で発生するイベントは、同じスレッド内の同じ位置での JVMDI クライアントによる処理中にトリガされることがあります。その種のイベント (タイプ y) が、タイプ x のイベントの処理中にトリガされたとします。前述の説明にある順序によると xy より前にレポートされるという場合は、同じ位置で発生したイベント y が、現在のスレッドおよび位置についてレポートされます。逆に、xy より前にレポートされないという場合は、イベント y は、現在のスレッドおよび位置についてレポートされません。たとえば、JVMDI_EVENT_SINGLE_STEP の処理中に現在位置にブレークポイントが設定された場合は、スレッドが現在位置を離れる前に、そのブレークポイントがレポートされます。

以下のイベントは、他のイベントと同じ位置で発生したと見なされることがありません。


VM および JVMDI クライアントの起動

VM の起動時に JVMDI クライアントを初期ロードする方法は、VM によって異なります。以下の説明は、Windows 版および Solaris 版 Sun J2SE 1.2 の旧来の VM に適用されます。

JVMDI クライアントを適切にロードして実行するには、VM の起動時に次のコマンド行引数が必要です。

-Xdebug
デバッグを有効にする
-Xnoagent
デフォルトのデバッグエージェント (jdb で使われる) を実行しないようにする
-Djava.compiler=NONE
JIT を無効にする。Classic VM は、JIT が有効な状態でのデバッグをサポートしていない
-Xrun:
JVMDI クライアントを含むライブラリと、起動時に渡されるオプションの文字列を指定する。ライブラリは、次のプロトタイプを持つ起動関数をエクスポートしている必要がある
JNIEXPORT jint JNICALL
JVM_OnLoad(JavaVM *vm, char *options, void *reserved)
この関数は、起動時に VM によって呼び出される。たとえば、オプション -Xrunfoo:opt1,opt2 が指定された場合、VM は、Windows では共用ライブラリ foo.dll を、Solaris では共用ライブラリ libfoo.so をロードしようとする。次に、VM は、JVM_OnLoad を探し、「opt1,opt2」を第 2 引数に指定して呼び出そうとする。この呼び出しの時点で VM はまだ初期化されていないので、JVM_OnLoad 内で安全に実行できる処理はごく限られている。VM が安全に実行できるのは、オプションの処理や、SetEventHook を使ってイベントフックを設定する処理である。VM 初期化イベントについてイベントフックが呼び出されたあと、JVMDI クライアントは、自身の初期化を完了することができる

Copyright © 1996-2004 Sun Microsystems, Inc.All Rights Reserved.

コメントの送付先: java-debugger@sun.com.

Sun