これらは, JNI の機能(より具体的に言うと JNI 関数全般)を実現するためのクラス.
保守運用機能のためのクラス (DTrace 用のフック点を管理するためのクラス) (See: here for details).
DTrace のフック点(より具体的に言うと JNI 関数のリターン時用のフック点)の生成処理を簡単に行うための補助クラス. ソースコード上のスコープに連動して自動的にフック点を生成する.
(なお, これらのクラスは DTRACE 機能が有効な場合 (= DTRACE_ONLY() が空文字列に展開されない場合) にのみ定義される)
デストラクタで DTrace のフック処理を呼び出すだけ.
DTraceReturnProbeMark_* はソースコード上で直接定義はされておらず, 以下のマクロを使って間接的に定義されている.
また, 使用する際にも以下のマクロを使って間接的に使用される.
またこれらのラッパーとして, 以下のマクロも用意されている (型に応じて void 用とそれ以外用を使い分ける).
(返値が float/double なら DT_RETURN_MARK_DECL(), それ以外なら DT_VOID_RETURN_MARK_DECL() に展開される)
(返値が float/double なら DT_RETURN_MARK(), それ以外なら DT_VOID_RETURN_MARK() に展開される)
((cite: hotspot/src/share/vm/prims/jni.cpp))
// The DT_RETURN_MARK macros create a scoped object to fire the dtrace
// '-return' probe regardless of the return path is taken out of the function.
// Methods that have multiple return paths use this to avoid having to
// instrument each return path. Methods that use CHECK or THROW must use this
// since those macros can cause an immedate uninstrumented return.
//
// In order to get the return value, a reference to the variable containing
// the return value must be passed to the contructor of the object, and
// the return value must be set before return (since the mark object has
// a reference to it).
//
// Example:
// DT_RETURN_MARK_DECL(SomeFunc, int);
// JNI_ENTRY(int, SomeFunc, ...)
// int return_value = 0;
// DT_RETURN_MARK(SomeFunc, int, (const int&)return_value);
// foo(CHECK_0)
// return_value = 5;
// return return_value;
// JNI_END
((cite: hotspot/src/share/vm/prims/jni.cpp))
#define DT_RETURN_MARK_DECL(name, type) \
HS_DTRACE_PROBE_DECL1(hotspot_jni, name##__return, type); \
DTRACE_ONLY( \
class DTraceReturnProbeMark_##name { \
public: \
const type& _ret_ref; \
DTraceReturnProbeMark_##name(const type& v) : _ret_ref(v) {} \
~DTraceReturnProbeMark_##name() { \
HS_DTRACE_PROBE1(hotspot_jni, name##__return, _ret_ref); \
} \
} \
)
((cite: hotspot/src/share/vm/prims/jni.cpp))
// Void functions are simpler since there's no return value
#define DT_VOID_RETURN_MARK_DECL(name) \
HS_DTRACE_PROBE_DECL0(hotspot_jni, name##__return); \
DTRACE_ONLY( \
class DTraceReturnProbeMark_##name { \
public: \
~DTraceReturnProbeMark_##name() { \
HS_DTRACE_PROBE0(hotspot_jni, name##__return); \
} \
} \
)
((cite: hotspot/src/share/vm/prims/jni.cpp))
// Place these macros in the function to mark the return. Non-void
// functions need the type and address of the return value.
#define DT_RETURN_MARK(name, type, ref) \
DTRACE_ONLY( DTraceReturnProbeMark_##name dtrace_return_mark(ref) )
#define DT_VOID_RETURN_MARK(name) \
DTRACE_ONLY( DTraceReturnProbeMark_##name dtrace_return_mark )
((cite: hotspot/src/share/vm/prims/jni.cpp))
// Choose DT_RETURN_MARK macros based on the type: float/double -> void
// (dtrace doesn't do FP yet)
#define DT_RETURN_MARK_DECL_FOR(TypeName, name, type) \
FP_SELECT(TypeName, \
DT_RETURN_MARK_DECL(name, type), DT_VOID_RETURN_MARK_DECL(name) )
#define DT_RETURN_MARK_FOR(TypeName, name, type, ref) \
FP_SELECT(TypeName, \
DT_RETURN_MARK(name, type, ref), DT_VOID_RETURN_MARK(name) )
((cite: hotspot/src/share/vm/prims/jni.cpp))
// Use these to select distinct code for floating-point vs. non-floating point
// situations. Used from within common macros where we need slightly
// different behavior for Float/Double
#define FP_SELECT_Boolean(intcode, fpcode) intcode
#define FP_SELECT_Byte(intcode, fpcode) intcode
#define FP_SELECT_Char(intcode, fpcode) intcode
#define FP_SELECT_Short(intcode, fpcode) intcode
#define FP_SELECT_Object(intcode, fpcode) intcode
#define FP_SELECT_Int(intcode, fpcode) intcode
#define FP_SELECT_Long(intcode, fpcode) intcode
#define FP_SELECT_Float(intcode, fpcode) fpcode
#define FP_SELECT_Double(intcode, fpcode) fpcode
#define FP_SELECT(TypeName, intcode, fpcode) \
FP_SELECT_##TypeName(intcode, fpcode)
See: here for details
デバッグ用(開発時用)のクラス (#ifdef ASSERT 時にしか定義されない).
JNI 関数が呼び出された際に, その関数名や引数を tty に出力するための一時オブジェクト(StackObjクラス).
((cite: hotspot/src/share/vm/prims/jni.cpp))
#ifdef ASSERT
((cite: hotspot/src/share/vm/prims/jni.cpp))
class JNITraceWrapper : public StackObj {
JNIWrapper マクロ内で(のみ)使用されている.
(なお, JNIWrapper マクロは #ifdef ASSERT でない場合には空文字列として定義されている. 以下の #else 以降が #ifdef ASSERT でない場合)
((cite: hotspot/src/share/vm/prims/jni.cpp))
#define JNIWrapper(arg) JNICountWrapper(arg); JNITraceWrapper(arg)
#else
#define JNIWrapper(arg)
そして, JNIWrapper マクロは各 JNI 関数の先頭に置かれている. このため各 JNI 関数が呼び出されると JNITraceWrapper による出力が行われる.
((cite: hotspot/src/share/vm/prims/jni.cpp))
JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderRef,
const jbyte *buf, jsize bufLen))
JNIWrapper("DefineClass");
行う処理は, コンストラクタで tty->print() を呼んで出力するだけ.
なお, このクラスは (デバッグ時であることに加えて) TraceJNICalls オプションが指定されている場合にしか働かない.
((cite: hotspot/src/share/vm/prims/jni.cpp))
JNITraceWrapper(const char* format, ...) {
if (TraceJNICalls) {
va_list ap;
va_start(ap, format);
tty->print("JNI ");
tty->vprint_cr(format, ap);
va_end(ap);
}
}
このクラスは JNI 関数用だが, CVMI 関数にも JVMTraceWrapper という類似のクラスが存在する.
See: here for details
デバッグ用(開発時用)のクラス (#ifdef ASSERT 時にしか定義されない).
各 JNI 関数が呼び出された回数を記録する.
((cite: hotspot/src/share/vm/prims/jni.cpp))
#ifdef ASSERT
((cite: hotspot/src/share/vm/prims/jni.cpp))
class JNIHistogramElement : public HistogramElement {
(なお, 以下の使われ方は HistogramElement のテンプレ通り (See: HistogramElement, Histogram))
JNIHistogram という大域変数の Histogram オブジェクト内に(のみ)格納されている.
((cite: hotspot/src/share/vm/prims/jni.cpp))
Histogram* JNIHistogram;
JNICountWrapper マクロ内で(のみ)生成されている.
((cite: hotspot/src/share/vm/prims/jni.cpp))
#define JNICountWrapper(arg) \
static JNIHistogramElement* e = new JNIHistogramElement(arg); \
/* There is a MT-race condition in VC++. So we need to make sure that that e has been initialized */ \
if (e != NULL) e->increment_count()
そして, このマクロは JNIWrapper マクロ内で(のみ)使用されている.
(なお, JNIWrapper マクロは #ifdef ASSERT でない場合には空文字列として定義されている. 以下の #else 以降が #ifdef ASSERT でない場合)
((cite: hotspot/src/share/vm/prims/jni.cpp))
#define JNIWrapper(arg) JNICountWrapper(arg); JNITraceWrapper(arg)
#else
#define JNIWrapper(arg)
そして, JNIWrapper マクロは各 JNI 関数の先頭に置かれている. このため各 JNI 関数が呼び出されると JNIHistogramElement による呼び出し回数の記録処理が行われる.
((cite: hotspot/src/share/vm/prims/jni.cpp))
JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderRef,
const jbyte *buf, jsize bufLen))
JNIWrapper("DefineClass");
このクラスは JNI 関数用だが, CVMI 関数にも JVMHistogramElement という類似のクラスが存在する.
See: here for details
JNI の関数 (より具体的に言うと, Call*Method*() 関数および NewObject*() 関数) を実装するためのクラス (の基底クラス).
HotSpot 内部の ABI に従うように引数を詰め直す処理を行う (See: here and here for details).
((cite: hotspot/src/share/vm/prims/jni.cpp))
class JNI_ArgumentPusher : public SignatureIterator {
なお, このクラス自体は abstract class であり, 実際に使われるのはサブクラス.
((cite: hotspot/src/share/vm/prims/jni.cpp))
virtual void get_bool () = 0;
virtual void get_char () = 0;
virtual void get_short () = 0;
virtual void get_byte () = 0;
virtual void get_int () = 0;
virtual void get_long () = 0;
virtual void get_float () = 0;
virtual void get_double () = 0;
virtual void get_object () = 0;
See: here for details
JNI_ArgumentPusher クラスの具象サブクラスの1つ.
このクラスは, 関数名の最後が 'A' で終わらない JNI 関数用 (つまり, 引数を va_list に入れて渡す関数 or 関数自体が可変長引数関数となっている関数用).
((cite: hotspot/src/share/vm/prims/jni.cpp))
class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher {
以下の JNI 関数の処理で(のみ)使用されている (See: here and here for details).
See: here for details
JNI_ArgumentPusher クラスの具象サブクラスの1つ.
このクラスは, 関数名の最後が 'A' で終わる JNI 関数用 (つまり, 引数を jvalue の配列に入れて渡す関数用).
((cite: hotspot/src/share/vm/prims/jni.cpp))
class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
以下の JNI 関数の処理で(のみ)使用されている (See: here and here for details).
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.