これらは, JNI の機能(より具体的に言うと JNI 参照(JNI references))を実現するためのクラス (See: here and here for details).
JNI 参照(JNI references)は, JNIHandles クラスと JNIHandleBlock クラスによって実装されている (なお, JNIHandles クラスの方は AllStatic クラス).
実際の JNI 参照は「JNIHandleBlock オブジェクト内を指すポインタ」として実装されており, それを操作するメソッドが JNIHandles クラスと JNIHandleBlock クラスに実装されている (See: here and here for details).
JNI 参照(JNI references)に関する処理を納めた名前空間(AllStatic クラス).
なお JNI 参照には Local, Global, Weak Global の 3種類があるが, 内部的には全てこのクラスが担当している.
((cite: hotspot/src/share/vm/runtime/jniHandles.hpp))
// Interface for creating and resolving local/global JNI handles
class JNIHandles : AllStatic {
HotSpot 内の様々な箇所で使用されている (#TODO).
(主に JNI に関する箇所で)
static フィールドである JNIHandles::_deleted_handle はダミーの handle 値 (消去された handle を示すためのもの) を入れておくフィールド.
(コメントによると「NULL は weak global JNI handle の処理で使っているので別の値を用意している」とのこと. (See: jni_DeleteLocalRef(), jni_DeleteGlobalRef(), jni_DeleteWeakGlobalRef()))
((cite: hotspot/src/share/vm/runtime/jniHandles.hpp))
static oop _deleted_handle; // Sentinel marking deleted handles
((cite: hotspot/src/share/vm/runtime/jniHandles.hpp))
// Sentinel marking deleted handles in block. Note that we cannot store NULL as
// the sentinel, since clearing weak global JNI refs are done by storing NULL in
// the handle. The handle may not be reused before destroy_weak_global is called.
static oop deleted_handle() { return _deleted_handle; }
See: here for details
JNI 参照(JNI references)を束ねておくためのコンテナクラス.
JNI 用語で言うと「ローカル参照フレーム」のようなもの (というか, 実際に JNI の PushLocalFrame()/PopLocalFrame() はこのコンテナが切り替わることで実装されている). ただし HotSpot 内では, Local references だけでなく, Global references や Weak Global references も全て JNIHandleBlock で管理されている.
なお, 1つの JNIHandleBlock には最大で 32 個の JNI 参照しか格納できない (内部構造も参照). このため Local, Global, Weak Global の各 JNI 参照は, それぞれが複数個の JNIHandleBlock によって管理されている.
((cite: hotspot/src/share/vm/runtime/jniHandles.hpp))
// JNI handle blocks holding local/global JNI handles
class JNIHandleBlock : public CHeapObj {
以下の箇所に(のみ)格納されている.
JNI Global References を束ねておくための JNIHandleBlock.
(正確には, このフィールドは JNIHandleBlock の線形リストを格納するフィールド. JNIHandleBlock オブジェクトは _next フィールドで次の JNIHandleBlock オブジェクトを指せる構造になっている. この線形リストに JNI Global reference 用の全ての JNIHandleBlock オブジェクトがつながれている)
((cite: hotspot/src/share/vm/runtime/jniHandles.cpp))
JNIHandleBlock* JNIHandles::_global_handles = NULL;
JNI Weak Global References を束ねておくための JNIHandleBlock.
(正確には, このフィールドは JNIHandleBlock の線形リストを格納するフィールド. JNIHandleBlock オブジェクトは _next フィールドで次の JNIHandleBlock オブジェクトを指せる構造になっている. この線形リストに JNI Weak Global reference 用の全ての JNIHandleBlock オブジェクトがつながれている)
((cite: hotspot/src/share/vm/runtime/jniHandles.cpp))
JNIHandleBlock* JNIHandles::_weak_global_handles = NULL;
JNI Local References を束ねておくための JNIHandleBlock.
(正確には, このフィールドは JNIHandleBlock の線形リストを格納するフィールド. JNIHandleBlock オブジェクトは _next フィールドで次の JNIHandleBlock オブジェクトを指せる構造になっている. この線形リストにそのスレッドの JNI Localreference 用の全ての JNIHandleBlock オブジェクトがつながれている)
(より正確には, このフィールドは「JNIHandleBlock の線形リストの線形リスト」を格納するフィールド. JNIHandleBlock オブジェクトは pop_frame_link フィールドで次の JNIHandleBlock オブジェクトを指せる構造になっている. _next フィールドで構成された線形リストの先頭の JNIHandleBlock オブジェクトは, _pop_frame_link フィールドで次の線形リストの先頭を指す. _next フィールドで構成された線形リストが 1つのローカル参照フレームに対応する. _popframe_link フィールドで構成された「線形リストの線形リスト」は, そのスレッドが PushLocalFrame() で作成した全てのローカル参照フレームに対応する)
((cite: hotspot/src/share/vm/runtime/thread.hpp))
// Active_handles points to a block of handles
JNIHandleBlock* _active_handles;
スレッドローカルなフリーリスト. あるスレッドが確保した JNIHandleBlock は, 不要になっても解放はされず, 代わりにこのスレッドローカルなフリーリストにつながれる. (See: JNIHandleBlock::allocate_block(), JNIHandleBlock::release_block())
(正確には, このフィールドは JNIHandleBlock の線形リストを格納するフィールド(フリーリスト). JNIHandleBlock オブジェクトは _next フィールドで次の JNIHandleBlock オブジェクトを指せる構造になっている)
((cite: hotspot/src/share/vm/runtime/thread.hpp))
// One-element thread local free list
JNIHandleBlock* _free_handle_block;
大域的なフリーリスト (See: JNIHandleBlock::allocate_block(), JNIHandleBlock::release_block())
(正確には, このフィールドは JNIHandleBlock の線形リストを格納するフィールド(フリーリスト). JNIHandleBlock オブジェクトは _next フィールドで次の JNIHandleBlock オブジェクトを指せる構造になっている. 未使用な JNIHandleBlock オブジェクト(でスレッドローカルなフリーリストにつながれていないもの)は, 全てこの線形リストに格納されている)
((cite: hotspot/src/share/vm/runtime/jniHandles.hpp))
static JNIHandleBlock* _block_free_list; // Free list of currently unused blocks
デバッグ用(開発時用)のフィールド (#ifndef PRODUCT 時にしか定義されない). 全ての JNIHandleBlock を格納したリスト
(格納している JNIHandleBlock オブジェクト自体は, 他の格納箇所と重複).
(正確には, このフィールドは JNIHandleBlock の線形リストを格納するフィールド. JNIHandleBlock オブジェクトは _block_list_link フィールドで次の JNIHandleBlock オブジェクトを指せる構造になっている)
JNIHandleBlock::allocate_block() というファクトリメソッドが用意されており, その中で(のみ)生成されている. そして, このファクトリメソッドは, 現在は以下のパスで(のみ)呼び出されている.
JNIHandles::global_handles フィールドおよび JNIHandles::weak_global_handles の初期化処理
各スレッドオブジェクト (のローカル参照フレーム) の初期化処理
CompilerThread による JIT コンパイル処理の開始時 (= CompilerThread のローカル参照フレームの初期化処理)
JVMTI のイベント通知処理時 (= コールバックの呼び出し処理時)
ランタイムによる Java のメソッドの呼び出し時
JNI の PushLocalFrame() が呼ばれた際
使用中の JNIHandleBlock に空きがなくなった際
定義されているフィールドは以下の通り.
_handles というフィールドに oop の配列を保持しており, 最大 32 個の oop を入れることができる. どこまで使っているかは _top というフィールドに保持している.
JNIHandle が 32 個以上になった場合には複数の JNIHandleBlock を使って管理する. その場合, _next フィールドで次の JNIHandleBlock へとリスト状につながる.
JNI 参照 (の参照先) を格納する oop 配列. 現在は 1つの JNIHandleBlock に最大 32 個の oop を格納することができる.
(なお, 現在の JNI 参照の実体は「この配列内の対応箇所を指すポインタ」になっている)
((cite: hotspot/src/share/vm/runtime/jniHandles.hpp))
enum SomeConstants {
block_size_in_oops = 32 // Number of handles per handle block
};
_handles 配列中で未使用な部分の先頭を示す. _handles は先頭から使っていくため _top 以降の箇所は未使用.
線形リストを構成するためのポインタ. 次の JNIHandleBlock を指す.
(1つの JNIHandleBlock には最大で 32 個しか JNI 参照を確保できないため, 複数個の JNIHandleBlock からなる線形リストで JNI 参照が管理される)
(また, 未使用の JNIHandleBlock の場合はフリーリストを構成するために使用される)
線形リストを構成するためのポインタ. _next による線形リスト中で現在使用している最後の JNIHandleBlock を指す. _next でつながるリストは先頭から使用していくため, 新しい JNI 参照の確保は _last から行われる.
線形リストを構成するためのポインタ. 次の JNIHandleBlock を指す
(このフィールドは JNI の PushLocalFrame()/PopLocalFrame() のためのもの).
_handles 中で delete された箇所を示すフィールド.
(正確には _handles 中の全ての delete 箇所を示すフリーリスト. _handles 中の delete された箇所には, このフリーリスト中での次要素を指すポインタが埋め込まれる)
(より正確には, delete された瞬間には JNIHandles::_deleted_handle の値が書き込まれ, その後 JNIHandleBlock::rebuild_free_list() が呼ばれた際に, 全ての delete 箇所が 1本のフリーリストにつながれる)
JNIHandleBlock::rebuild_free_list() を呼び出すタイミングを制御するフィールド. 「あと何回 JNI 参照を確保行したら次回の JNIHandleBlock::rebuild_free_list() を呼び出すか」を示す.
(このフィールドは JNIHandleBlock::rebuild_free_list() の処理後に値がセットされる. 値は JNIHandleBlock::allocate_handle() を呼ぶ度に減少し, 0 になったら次の JNIHandleBlock::rebuild_free_list() が呼び出される)
デバッグ用(開発時用)のフィールド (#ifndef PRODUCT 時にしか定義されない).
線形リストを構成するためのポインタ. JNIHandleBlock::_block_list のリストを作るために使用される.
((cite: hotspot/src/share/vm/runtime/jniHandles.hpp))
oop _handles[block_size_in_oops]; // The handles
int _top; // Index of next unused handle
JNIHandleBlock* _next; // Link to next block
// The following instance variables are only used by the first block in a chain.
// Having two types of blocks complicates the code and the space overhead in negligble.
JNIHandleBlock* _last; // Last block in use
JNIHandleBlock* _pop_frame_link; // Block to restore on PopLocalFrame call
oop* _free_list; // Handle free list
int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list
#ifndef PRODUCT
JNIHandleBlock* _block_list_link; // Link for list below
See: here for details
保守運用機能のためのクラス (Dynamic Attach 機能及びスレッドダンプ機能用のクラス).
JNIHandles クラス内で使用される補助クラス. JNI の Weak Global Handle を辿る処理で使用される Closure.
((cite: hotspot/src/share/vm/runtime/jniHandles.cpp))
class AlwaysAliveClosure: public BoolObjectClosure {
以下の箇所で(のみ)使用されている.
そして, これらの関数は現在は以下のパスで(のみ)呼び出されている.
* (?? 使用箇所が見当たらない) JNIHandles::print() -> JNIHandles::print_on() * 保守運用機能のための処理 (Dynamic Attach 機能及びスレッドダンプ機能用の処理) VM_PrintJNI::doit() -> JNIHandles::print_on() * デバッグ用(開発時用)の処理 Universe::verify() -> JNIHandles::verify()
同名のクラスが hotspot/src/share/vm/memory/referenceProcessor.cpp にいたりするが (そして処理もそっくりだが), 特に関係は無い模様.
See: here for details
保守運用機能のためのクラス (Dynamic Attach 機能及びスレッドダンプ機能用のクラス).
JNIHandles クラス内で使用される補助クラス. JNI の Weak Global Handle を辿る処理で使用される Closure.
((cite: hotspot/src/share/vm/runtime/jniHandles.cpp))
class CountHandleClosure: public OopClosure {
JNIHandles::print_on() 内で(のみ)使用されている. そして, この関数は現在は以下のパスで(のみ)呼び出されている.
* 保守運用機能のための処理 (Dynamic Attach 機能及びスレッドダンプ機能用の処理) VM_PrintJNI::doit() -> JNIHandles::print_on()
同名のクラスが hotspot/src/share/vm/memory/referenceProcessor.cpp にいたりするが (そして処理もそっくりだが), 特に関係は無い模様.
See: here for details
デバッグ用(開発時用)のクラス.
JNIHandles クラス内で使用される補助クラス.
((cite: hotspot/src/share/vm/runtime/jniHandles.cpp))
class VerifyHandleClosure: public OopClosure {
JNIHandles::verify() 内で(のみ)使用されている. そして, この関数は現在は以下のパスで(のみ)呼び出されている.
Universe::verify() -> JNIHandles::verify()
処理としては, 単に oopDesc::verify() を呼び出すだけ.
((cite: hotspot/src/share/vm/runtime/jniHandles.cpp))
virtual void do_oop(oop* root) {
(*root)->verify();
}
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.