Java

JavaTM Virtual Machine Debug Interface リファレンス

目次

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


はじめに

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

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

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

JVMDI は、Java Platform Debugger Architecture 内の 1 つのレイヤを構成します。このアーキテクチャには、より高レベルのアウトプロセスデバッガインタフェースが含まれています。多くのデバッガツールには、JVMDI よりもこれらのより高レベルのインタフェースの方が適しています。Java Platform Debugger Architecture の詳細については、Java Developer Connection を参照してください。


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 が呼び出された)。このビットが設定されると、statusPtr を介して返される状態は、一時停止する前にスレッドの状態を参照する

JVMDI_SUSPEND_STATUS_BREAK
スレッドはブレークポイントによって停止。このビットは、スレッドが現在のスレッドであるか、またはスレッドが一時停止中である場合にのみ設定される
この関数は、汎用エラー、または次のエラーのどれかを返します。

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_NULL_POINTER
ポインタが無効

すべてのスレッドの取得

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

実行中のすべてのスレッドを Virtual Machine に認識させます。VM に接続していないネイティブスレッドは、返される一覧に含まれません。

パラメータ:

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

JVMDI_ERROR_NULL_POINTER
ポインタが無効


スレッドの一時停止

jvmdiError
SuspendThread(jthread thread)

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

パラメータ:

thread
一時停止にするスレッド

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

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_THREAD_SUSPENDED
スレッドはすでに停止中

スレッドの実行再開

jvmdiError
ResumeThread(jthread thread)

一時停止中のスレッドの実行を再開します。SuspendThread によって一時停止したスレッドの実行をすべて再開します。

パラメータ:

thread
再開するスレッド

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

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_THREAD_NOT_SUSPENDED
スレッドは一時停止中ではない

JVMDI_ERROR_INVALID_TYPESTATE
スレッドの状態が変更されたので矛盾している

スレッドの停止

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 構造体のフィールドには、所有するモニターの詳細が入ります。この関数を現在のスレッド以外のスレッドに対して呼び出す場合は、指定するスレッドを一時停止する必要があります。

この機能はオプションで、すべての Virtual Machine に実装しなければならないわけではありません。特定の Virtual Machine でサポートされている機能を知るには、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 を使ってオブジェクトのモニターに入るのを待っているか、オブジェクトのモニターを獲得し直すのを待っている場合は、そのオブジェクトを取得します。この関数を現在のスレッド以外のスレッドに対して呼び出す場合は、指定するスレッドを一時停止する必要があります。

この機能はオプションで、すべての Virtual Machine に実装しなければならないわけではありません。特定の Virtual Machine でサポートされている機能を知るには、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)
特定のスレッドグループ内で作成されたスレッドおよびスレッドグループを取得します。

パラメータ:

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
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_OPAQUE_FRAME
frame は Java フレームではない

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

フレームのポップの通知

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

パラメータ:

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

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

JVMDI_ERROR_NULL_POINTER
ポインタが無効

JVMDI_ERROR_OPAQUE_FRAME
frame は Java フレームではない

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
変数のスロット番号
value
変数の新しい値

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

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()
この Virtual Machine で設定されているブレークポイントをすべて解除します。


監視されるフィールド


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

jvmdiError
SetFieldAccessWatch(jclass clazz, jfieldID field)

clazz および field で指定されたフィールドへのアクセスが行われようとしているときに、JVMDI_EVENT_FIELD_ACCESS イベントを生成します。イベントは、ClearFieldAccessWatch を使ってキャンセルされるまで、フィールドの各アクセスに対して生成されます。Java 言語コードまたは JNI からのフィールドアクセスは監視され、ほかの方法で修正されたフィールドは監視されません。JVMDI ユーザは、ユーザ自身のフィールドアクセスによって監視が開始されることに注意してください。1 つのフィールドに対し、フィールドアクセスの監視を 1 つだけ設定できます。フィールドの修正はアクセスとはみなされません。 修正を監視するには、SetFieldModificationWatch を使います。

この機能はオプションで、すべての Virtual Machine に実装しなければならないわけではありません。特定の Virtual Machine でサポートされている機能を知るには、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 つだけ設定できます。

この機能はオプションで、すべての Virtual Machine に実装しなければならないわけではありません。特定の Virtual Machine でサポートされている機能を知るには、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 Virtual Machine 仕様で定義されています。

クラスが配列クラスの場合、その 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_PREAPRED

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

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)
クラスオブジェクト参照が配列を指すかどうかを判定します。クラスが配列である場合、jbooleanJNI_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
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 構造体のフィールドは、モニターの詳細で構成されます。モニターの状態に影響を与える可能性のある各スレッドは、一時停止されるか、または現在のスレッドである必要があります。

この機能はオプションで、すべての Virtual Machine に実装しなければならないわけではありません。特定の Virtual Machine でサポートされている機能を知るには、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 Virtual Machine 仕様で定義されています。

パラメータ:

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 を介してそのフィールドが合成であるかどうかを示す値を返します。合成フィールドはコンパイラによって生成されますが、元のソースコード内には存在しません。

この機能はオプションで、すべての Virtual Machine に実装しなければならないわけではありません。特定の Virtual Machine でサポートされている機能を知るには、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 により返します。このシグニチャーは、Java Virtual Machine 仕様ではメソッド記述子とも呼ばれている JNI シグニチャーです。 これは、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 Virtual Machine 仕様で定義されています。

パラメータ:

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;                /* upto 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
ポインタが無効

バイトコードの取得

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

この機能はオプションで、すべての Virtual Machine に実装しなければならないわけではありません。特定の Virtual Machine でサポートされている機能を知るには、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)

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

この機能はオプションで、すべての Virtual Machine に実装しなければならないわけではありません。特定の Virtual Machine でサポートされている機能を知るには、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 モニターを作成します。

パラメータ:

名前
モニターを識別する UTF-8 名
monitorPtr
戻り値で、作成されたモニターを示す

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

JVMDI_ERROR_NULL_POINTER
ポインタが無効

raw モニターの破棄

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

パラメータ:

monitor
モニター

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

JVMDI_ERROR_NULL_POINTER
ポインタが無効

raw モニターの開始

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

パラメータ:

monitor
モニター

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

JVMDI_ERROR_INVALID_MONITOR
モニターが無効

raw モニターの終了

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

パラメータ:

monitor
モニター

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

JVMDI_ERROR_INVALID_MONITOR
モニターが無効

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 モニターで待機中の単一のスレッドに通知します。

パラメータ:

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 の場合は、このイベントはグローバルに有効または無効になります。 それ以外の場合は、特定のスレッドに対して有効または無効になります。特定のスレッドに対してイベントが生成されるのは、イベントがスレッドレベルまたはグローバルレベルのいずれかで有効になっている場合です。

特定のイベントについての情報は、あとの項を参照してください。

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

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

各イベントで関数が呼び出されるように設定します。イベントの詳細は、このドキュメントのあとの項で説明します。

パラメータ:

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

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

JVMDI_ERROR_INVALID_THREAD
thread が無効

JVMDI_ERROR_INVALID_EVENT_TYPE
eventType の値が無効


その他の関数


ロード済みクラスの取得

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

Virtual Machine にロードされている全クラスの配列を返します。 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 の場合は、この関数によって Virtual Machine 内にロードされたすべてのクラスが返されます。 classCountPtr によって配列内のクラスの数が返され、classesPtr によって配列自体が返されます。Deallocate() を使って配列を解放する必要があります。

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

パラメータ:

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

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

JVMDI_ERROR_NULL_POINTER
ポインタが無効

バージョン番号の取得

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;
} 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
この Virtual Machine ではデバッグが有効になっていない。JVMDI が使用できない

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

JVMDI_ERROR_VM_DEAD
Virtual Machine が動作していない

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

関数特有のエラー

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

JVMDI_ERROR_INVALID_THREAD
渡されたスレッドが有効でないか終了している

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
この Virtual Machine では、この機能は実装されていない

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 クライアントは、アプリケーション内で発生する多くのイベントについての通知を受けることができます。

イベントを処理するには、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 で可能な限り細かくスレッドの実行を追跡できます。ステップ実行イベントは、スレッドが新しい位置に達する度に生成されます。通常、ステップ実行イベントは、Virtual Machine 仕様に定義されているように、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 節に到達するという保証はありません。呼び出しスタック上で throw の位置と catch 節の間に呼び出しスタック上のネイティブメソッドがある場合は、それらのネイティブメソッドの 1 つによって例外がリセットされる可能性があります。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 によって異なります。以下の説明は、Sun の提供する、Windows 版および Solaris 版の旧来の VM に適用されます。

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

-Xdebug
デバッグを有効にする
-Xnoagent
jdb で使われるデフォルトのデバッグエージェントを実行しないようにする
-Djava.compiler=NONE
JIT を無効にする。旧来の 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 © 1998-1999 Sun Microsystems, Inc. All Rights Reserved.

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

Sun