hotspot/src/share/vm/runtime/vmThread.cpp
void VMThread::run() {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(this == vm_thread(), "check");
{- -------------------------------------------
(1) Thread::initialize_thread_local_storage() を呼んで,
現在実行中のネイティブスレッドにこの VMThread オブジェクトを対応付けておく.
---------------------------------------- -}
this->initialize_thread_local_storage();
{- -------------------------------------------
(1) Thread::record_stack_base_and_size() を呼んで, スタック領域関連のフィールドを初期化する.
---------------------------------------- -}
this->record_stack_base_and_size();
{- -------------------------------------------
(1) カレントスレッドの JNI ローカル参照フレームを作成しておく.
(JNIHandleBlock::allocate_block() で新しい JNIHandleBlock を作成し,
それを Thread::set_active_handles() でカレントスレッドにセットする.
See: [here](no3059hRF.html) for details)
---------------------------------------- -}
// Notify_lock wait checks on active_handles() to rewait in
// case of spurious wakeup, it should wait on the last
// value set prior to the notify
this->set_active_handles(JNIHandleBlock::allocate_block());
{- -------------------------------------------
(1) Notify_lock に対して Monitor::notify() を呼んでおく.
(これは VMThread の作成元である Threads::create_vm() との同期処理.
See: Threads::create_vm())
---------------------------------------- -}
{
MutexLocker ml(Notify_lock);
Notify_lock->notify();
}
// Notify_lock is destroyed by Threads::create_vm()
{- -------------------------------------------
(1) os::set_native_priority() を呼んで, VMThread の優先度を変更しておく.
---------------------------------------- -}
int prio = (VMThreadPriority == -1)
? os::java_to_os_priority[NearMaxPriority]
: VMThreadPriority;
// Note that I cannot call os::set_priority because it expects Java
// priorities and I am *explicitly* using OS priorities so that it's
// possible to set the VM thread priority higher than any Java thread.
os::set_native_priority( this, prio );
{- -------------------------------------------
(1) VMThread::loop() を呼んで, VMThread のメイン処理を開始する.
---------------------------------------- -}
// Wait for VM_Operations until termination
this->loop();
{- -------------------------------------------
(1) (トレース出力)
(なお, ここでトレースを出すのには,
他の箇所から大量の tty 出力があった場合に
それが完了するのを待ち受けるという意味もある.
実際, 大量の出力がある場合に待ち受けを行わないと,
以降の SafepointSynchronize がタイムアウトして異常終了する恐れがある.
Bug 6295565 も参照)
---------------------------------------- -}
// Note the intention to exit before safepointing.
// 6295565 This has the effect of waiting for any large tty
// outputs to finish.
if (xtty != NULL) {
ttyLocker ttyl;
xtty->begin_elem("destroy_vm");
xtty->stamp();
xtty->end_elem();
assert(should_terminate(), "termination flag must be set");
}
{- -------------------------------------------
(1) この後の終了処理で様々なリソースを開放していくので,
解放後のリソースにスレッドがうっかりアクセスしてしまわないように,
SafepointSynchronize::begin() で HotSpot を Safepoint 状態にしておく.
(Bug 4526887 も参照)
---------------------------------------- -}
// 4526887 let VM thread exit at Safepoint
SafepointSynchronize::begin();
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
if (VerifyBeforeExit) {
HandleMark hm(VMThread::vm_thread());
// Among other things, this ensures that Eden top is correct.
Universe::heap()->prepare_for_verify();
os::check_heap();
// Silent verification so as not to pollute normal output,
// unless we really asked for it.
Universe::verify(true, !(PrintGCDetails || Verbose));
}
{- -------------------------------------------
(1) CompileBroker::set_should_block() を呼んで, CompilerThread に停止要請を通知する.
(CompileBroker::set_should_block() を呼ぶと
CompileBroker::maybe_block() が true を返すようになり,
これによって CompilerThread が停止するようになる.
See: CompileBroker::maybe_block())
---------------------------------------- -}
CompileBroker::set_should_block();
{- -------------------------------------------
(1) VM_Exit::wait_for_threads_in_native_to_block() を呼んで,
native method を実行しているスレッドが停止するまで, 少しのあいだ待ってみる.
---------------------------------------- -}
// wait for threads (compiler threads or daemon threads) in the
// _thread_in_native state to block.
VM_Exit::wait_for_threads_in_native_to_block();
{- -------------------------------------------
(1) VMThread が終了したことを, jni_DestroyJavaVM() 内で
VMThread の終了を待っているスレッドに通知する.
(_terminated の値を変更することで,
VMThread::is_terminated() が true を返すようになり,
終了したことが相手に伝わる.
See: VMThread::wait_for_vm_thread_exit())
---------------------------------------- -}
// signal other threads that VM process is gone
{
// Note: we must have the _no_safepoint_check_flag. Mutex::lock() allows
// VM thread to enter any lock at Safepoint as long as its _owner is NULL.
// If that happens after _terminate_lock->wait() has unset _owner
// but before it actually drops the lock and waits, the notification below
// may get lost and we will have a hang. To avoid this, we need to use
// Mutex::lock_without_safepoint_check().
MutexLockerEx ml(_terminate_lock, Mutex::_no_safepoint_check_flag);
_terminated = true;
_terminate_lock->notify();
}
{- -------------------------------------------
(1) (VMThread の開放処理は, JNI の DestroyJavaVM() を呼び出したスレッドが, 同期的に行わないといけない.
これは, CodeHeap を開放する前に VMThread の削除が終わることを保証したいため.)
---------------------------------------- -}
// Deletion must be done synchronously by the JNI DestroyJavaVM thread
// so that the VMThread deletion completes before the main thread frees
// up the CodeHeap.
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.