これらは, CVMI の関数を実装するためのクラス.
デバッグ用(開発時用)のクラス (#ifdef ASSERT 時にしか定義されない).
CVMI 関数が呼び出された際に, その関数名や引数を tty に出力するための一時オブジェクト(StackObjクラス).
((cite: hotspot/src/share/vm/prims/jvm.cpp))
#ifdef ASSERT
((cite: hotspot/src/share/vm/prims/jvm.cpp))
class JVMTraceWrapper : public StackObj {
JVMWrapper{|2|3|4} マクロ内で(のみ)使用されている.
(なお, JVMWrapper* マクロは #ifdef ASSERT でない場合には空文字列として定義されている. 以下の #else 以降が #ifdef ASSERT でない場合)
((cite: hotspot/src/share/vm/prims/jvm.cpp))
#define JVMWrapper(arg1) JVMCountWrapper(arg1); JVMTraceWrapper(arg1)
#define JVMWrapper2(arg1, arg2) JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2)
#define JVMWrapper3(arg1, arg2, arg3) JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2, arg3)
#define JVMWrapper4(arg1, arg2, arg3, arg4) JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2, arg3, arg4)
#else
#define JVMWrapper(arg1)
#define JVMWrapper2(arg1, arg2)
#define JVMWrapper3(arg1, arg2, arg3)
#define JVMWrapper4(arg1, arg2, arg3, arg4)
#endif
そして JVMWrapper マクロは各 CVMI 関数の先頭に置かれている. このため各 CVMI 関数が呼び出されると JVMTraceWrapper による出力が行われる.
((cite: hotspot/src/share/vm/prims/jvm.cpp))
JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd))
JVMWrapper2("JVM_DefineClass %s", name);
行う処理は, コンストラクタで tty->print() を呼んで出力するだけ.
なお, このクラスは (デバッグ時であることに加えて) TraceJVMCalls オプションが指定されている場合にしか働かない.
((cite: hotspot/src/share/vm/prims/jvm.cpp))
JVMTraceWrapper(const char* format, ...) {
if (TraceJVMCalls) {
va_list ap;
va_start(ap, format);
tty->print("JVM ");
tty->vprint_cr(format, ap);
va_end(ap);
}
}
このクラスは CVMI 関数用だが, JNI 関数にも JNITraceWrapper という類似のクラスが存在する.
See: here for details
デバッグ用(開発時用)のクラス (#ifdef ASSERT 時にしか定義されない).
各 CVMI 関数が呼び出された回数を記録する.
((cite: hotspot/src/share/vm/prims/jvm.cpp))
#ifdef ASSERT
((cite: hotspot/src/share/vm/prims/jvm.cpp))
class JVMHistogramElement : public HistogramElement {
(なお, 以下の使われ方は HistogramElement のテンプレ通り (See: HistogramElement, Histogram))
JVMHistogram という大域変数の Histogram オブジェクト内に(のみ)格納されている.
((cite: hotspot/src/share/vm/prims/jvm.cpp))
Histogram* JVMHistogram;
JVMCountWrapper() マクロ内で(のみ)生成されている.
((cite: hotspot/src/share/vm/prims/jvm.cpp))
#define JVMCountWrapper(arg) \
static JVMHistogramElement* e = new JVMHistogramElement(arg); \
if (e != NULL) e->increment_count(); // Due to bug in VC++, we need a NULL check here eventhough it should never happen!
そして, このマクロは JVMWrapper マクロ内で(のみ)使用されている.
(なお, JVMWrapper* マクロは #ifdef ASSERT でない場合には空文字列として定義されている. 以下の #else 以降が #ifdef ASSERT でない場合)
((cite: hotspot/src/share/vm/prims/jvm.cpp))
#define JVMWrapper(arg1) JVMCountWrapper(arg1); JVMTraceWrapper(arg1)
#define JVMWrapper2(arg1, arg2) JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2)
#define JVMWrapper3(arg1, arg2, arg3) JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2, arg3)
#define JVMWrapper4(arg1, arg2, arg3, arg4) JVMCountWrapper(arg1); JVMTraceWrapper(arg1, arg2, arg3, arg4)
#else
#define JVMWrapper(arg1)
#define JVMWrapper2(arg1, arg2)
#define JVMWrapper3(arg1, arg2, arg3)
#define JVMWrapper4(arg1, arg2, arg3, arg4)
#endif
そして JVMWrapper マクロは各 CVMI 関数の先頭に置かれている. このため各 CVMI 関数が呼び出されると JVMHistogramElement による呼び出し回数の記録処理が行われる.
((cite: hotspot/src/share/vm/prims/jvm.cpp))
JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd))
JVMWrapper2("JVM_DefineClass %s", name);
このクラスは CVMI 関数用だが, JNI 関数にも JNIHistogramElement という類似のクラスが存在する.
See: here for details
CVMI 関数用 (より具体的に言うと, JVM_GetStackAccessControlContext() 用) の補助クラス (See: JVM_GetStackAccessControlContext()).
ある oop 配列を作業途中のあるスコープの中でだけ JavaThread オブジェクト内に格納しておきたい, という場合に使われる補助クラス.
((cite: hotspot/src/share/vm/prims/jvm.cpp))
class RegisterArrayForGC {
(JVM_GetStackAccessControlContext() の返値である java.security.AccessControlContext オブジェクト内には java.security.ProtectionDomain オブジェクトの配列を入れる必要がある. スレッドのスタックを辿って ProtectionDomain オブジェクトを集めた後, その ProtectionDomain を入れる配列を確保する時点で GC が起こると, せっかく集めた ProtectionDomain オブジェクトへのポインタが不正になる恐れがある. このため, これらの ProtectionDomain オブジェクトを JavaThread 内に入れて strong root 扱いにしている模様)
コンストラクタで JavaThread::register_array_for_gc() を呼んで指定の JavaThread 内に指定の配列を登録し, デストラクタで (同じく JavaThread::register_array_for_gc() を呼んで) 元に戻している.
((cite: hotspot/src/share/vm/prims/jvm.cpp))
RegisterArrayForGC(JavaThread *thread, GrowableArray<oop>* array) {
_thread = thread;
_thread->register_array_for_gc(array);
}
~RegisterArrayForGC() {
_thread->register_array_for_gc(NULL);
}
See: here for details
CVMI 関数 (より具体的に言うと JVM_GetClassContext() 関数) の処理で使用される一時オブジェクト(ResourceObjクラス). (なお, JVM_GetClassContext() は java.lang.SecurityManager.getClassContext() を実装するための関数. (See: JVM_GetClassContext()))
((cite: hotspot/src/share/vm/prims/jvm.cpp))
// Utility object for collecting method holders walking down the stack
class KlassLink: public ResourceObj {
単なる構造体のようなクラス. 内部には以下の2つの public フィールドのみを持つ (そしてメソッドはない).
((cite: hotspot/src/share/vm/prims/jvm.cpp))
KlassHandle klass;
KlassLink* next;
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.