hotspot/src/share/vm/runtime/vm_operations.cpp
int VM_Exit::wait_for_threads_in_native_to_block() {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
// VM exits at safepoint. This function must be called at the final safepoint
// to wait for threads in _thread_in_native state to be quiescent.
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint already");
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
Thread * thr_cur = ThreadLocalStorage::get_thread_slow();
Monitor timer(Mutex::leaf, "VM_Exit timer", true);
{- -------------------------------------------
(1) (変数宣言など)
(max_wait_user_thread 及び max_wait (= max_wait_compiler_thread) が最大待機時間を示す.
なお, 待機処理を行うループ内では 10 msec 単位でスリープするので, 実際の待機時間とは 10 倍のずれがある.
つまり, それぞれ 300 msec, 及び 10 sec を表す.)
(コメントによると,
user thread (JavaThread) の場合は, HotSpot 内のデータにアクセスするには native=>Java/VM transition を行う必要があり,
そこで停止させられるので, 待機時間は比較的短くていい.
一方 CompilerThread は, native=>Java/VM transition 無しで HotSpot 内のデータにアクセスできるため,
長めの待機時間を取っておく必要がある.
なお, 理屈の上では JavaThread については待たなくてもいいが,
HotSpot が終了する際にはスレッドが全部停止している方が望ましいので, 待機している.)
---------------------------------------- -}
// Compiler threads need longer wait because they can access VM data directly
// while in native. If they are active and some structures being used are
// deleted by the shutdown sequence, they will crash. On the other hand, user
// threads must go through native=>Java/VM transitions first to access VM
// data, and they will be stopped during state transition. In theory, we
// don't have to wait for user threads to be quiescent, but it's always
// better to terminate VM when current thread is the only active thread, so
// wait for user threads too. Numbers are in 10 milliseconds.
int max_wait_user_thread = 30; // at least 300 milliseconds
int max_wait_compiler_thread = 1000; // at least 10 seconds
int max_wait = max_wait_compiler_thread;
{- -------------------------------------------
(1) 以下の while ループ内で, native method を実行しているスレッドの終了を待ち受ける.
ループ内では, まず JavaThread の一覧を辿り, それらの内で native method を実行中のスレッドの個数を数える.
(また, native method を実行中のスレッドの内で CompilerThread である数も同時に数える)
その後, 数えた結果をもとにループを終了するかどうかを判断する.
以下のどれかの条件が成り立てば, ループは終了.
* native method を実行しているスレッドがいない場合 (以下の num_active が 0 の場合)
* ループ回数(以下の attempts)が max_wait 回数を超えた場合
* native method を実行しているのが user thread (JavaThread) だけであり, かつ
ループ回数(以下の attempts)が max_wait_user_thread 回数を超えた場合
---------------------------------------- -}
int attempts = 0;
while (true) {
int num_active = 0;
int num_active_compiler_thread = 0;
for(JavaThread *thr = Threads::first(); thr != NULL; thr = thr->next()) {
if (thr!=thr_cur && thr->thread_state() == _thread_in_native) {
num_active++;
if (thr->is_Compiler_thread()) {
num_active_compiler_thread++;
}
}
}
if (num_active == 0) {
return 0;
} else if (attempts > max_wait) {
return num_active;
} else if (num_active_compiler_thread == 0 && attempts > max_wait_user_thread) {
return num_active;
}
attempts++;
MutexLockerEx ml(&timer, Mutex::_no_safepoint_check_flag);
timer.wait(Mutex::_no_safepoint_check_flag, 10);
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.