hotspot/src/share/vm/runtime/vmThread.cpp
void VMThread::loop() {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(_cur_vm_operation == NULL, "no current one should be executing");
{- -------------------------------------------
(1) (以下の while ループが VMThread のメイン処理.
VMThread の lifetime のほとんどは, この無限ループに費やされる.
VMThread::should_terminate() が true になったら, VMThread は無限ループを抜けて終了する.
なお, VMThread::should_terminate() は HotSpot の終了処理が開始されると true になる.
See: VMThread::wait_for_vm_thread_exit())
---------------------------------------- -}
while(true) {
{- -------------------------------------------
(1.1) (変数宣言など)
---------------------------------------- -}
VM_Operation* safepoint_ops = NULL;
{- -------------------------------------------
(1.1) 新しい VM Operation 要求 (VM_Operation オブジェクト) を取得する.
(以下のブロック内で新しい VM Operation 要求が来るまで待機)
---------------------------------------- -}
//
// Wait for VM operation
//
// use no_safepoint_check to get lock without attempting to "sneak"
{ MutexLockerEx mu_queue(VMOperationQueue_lock,
Mutex::_no_safepoint_check_flag);
{- -------------------------------------------
(1.1.1) まず, VMOperationQueue::remove_next() で
新しい VM_Operation オブジェクトが来ていないか確認する.
---------------------------------------- -}
// Look for new operation
assert(_cur_vm_operation == NULL, "no current one should be executing");
_cur_vm_operation = _vm_queue->remove_next();
{- -------------------------------------------
(1.1.1) (トレース出力)
---------------------------------------- -}
// Stall time tracking code
if (PrintVMQWaitTime && _cur_vm_operation != NULL &&
!_cur_vm_operation->evaluate_concurrently()) {
long stall = os::javaTimeMillis() - _cur_vm_operation->timestamp();
if (stall > 0)
tty->print_cr("%s stall: %Ld", _cur_vm_operation->name(), stall);
}
{- -------------------------------------------
(1.1.1) もし VM_Operation オブジェクトが無ければ,
VMThread::should_terminate()が true になるか VM_Operation オブジェクトが得られるまで
以下の while ループ内で待ち続ける.
---------------------------------------- -}
while (!should_terminate() && _cur_vm_operation == NULL) {
{- -------------------------------------------
(1.1.1.1) VMOperationQueue_lock に対する Monitor::wait() で VM_Operation オブジェクトが来るまで待つ.
(ただし, 少なくともある程度の時間間隔で safepoint が行われるよう,
この wait() にはタイムアウト時間が指定されている.
現在は GuaranteedSafepointInterval でタイムアウト.)
---------------------------------------- -}
// wait with a timeout to guarantee safepoints at regular intervals
bool timedout =
VMOperationQueue_lock->wait(Mutex::_no_safepoint_check_flag,
GuaranteedSafepointInterval);
{- -------------------------------------------
(1.1.1.1) (以下は wait() が解けた後の処理)
---------------------------------------- -}
{- -------------------------------------------
(1.1.1.1) (トラブルシューティング用の処理) (関連する product オプションが指定されている場合にのみ実行) (See: SelfDestructTimer)
(もし起動後の経過時間が指定時間を超えていれば, ここで HotSpot を終了させる)
(終了させる場合には, ついでに(トレース出力)も出している)
---------------------------------------- -}
// Support for self destruction
if ((SelfDestructTimer != 0) && !is_error_reported() &&
(os::elapsedTime() > SelfDestructTimer * 60)) {
tty->print_cr("VM self-destructed");
exit(-1);
}
{- -------------------------------------------
(1.1.1.1) もし wait() がタイムアウトで終了していた場合は,
SafepointSynchronize::is_cleanup_needed() を呼んで
Safepoint 停止が必要かどうかを確認する.
必要な場合には, ここで SafepointSynchronize::begin() と
SafepointSynchronize::end() を呼び出す.
(これは, 少なくともある程度の時間間隔で safepoint を実行するための処理)
(なお, デバッグ用の SafepointALot オプションが指定されている場合は,
SafepointSynchronize::is_cleanup_needed() の値に寄らず
Safepoint 停止処理が行われる.)
---------------------------------------- -}
if (timedout && (SafepointALot ||
SafepointSynchronize::is_cleanup_needed())) {
MutexUnlockerEx mul(VMOperationQueue_lock,
Mutex::_no_safepoint_check_flag);
// Force a safepoint since we have not had one for at least
// 'GuaranteedSafepointInterval' milliseconds. This will run all
// the clean-up processing that needs to be done regularly at a
// safepoint
SafepointSynchronize::begin();
#ifdef ASSERT
if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot();
#endif
SafepointSynchronize::end();
}
{- -------------------------------------------
(1.1.1.1) VMOperationQueue::remove_next() で, 新しい VM_Operation オブジェクトを取得する.
---------------------------------------- -}
_cur_vm_operation = _vm_queue->remove_next();
{- -------------------------------------------
(1.1.1.1) 新しい VM_Operation オブジェクトを取得できた場合,
それが safepoint での実行を必要とするものかどうかを確認する.
もしそうであれば, ついでに safepoint で実行しないといけない他の VM_Operation もまとめて取得しておく.
---------------------------------------- -}
// If we are at a safepoint we will evaluate all the operations that
// follow that also require a safepoint
if (_cur_vm_operation != NULL &&
_cur_vm_operation->evaluate_at_safepoint()) {
safepoint_ops = _vm_queue->drain_at_safepoint_priority();
}
}
{- -------------------------------------------
(1.1.1) なお, should_terminate() が true になったら, VMThread は無限ループを抜ける
---------------------------------------- -}
if (should_terminate()) break;
} // Release mu_queue_lock
{- -------------------------------------------
(1.1) (ここまでが, 新しい VM Operation 要求 (VM_Operation オブジェクト) を取得する処理)
---------------------------------------- -}
{- -------------------------------------------
(1.1) 次に, 取得した VM_Operation オブジェクトを実際に実行する.
(以下のブロック内で VMThread::evaluate_operation() により VM_Operation を実行.
なお, safepoint 停止が必要かどうかに応じて処理を分けている.
詳細は以下参照)
---------------------------------------- -}
//
// Execute VM operation
//
{ HandleMark hm(VMThread::vm_thread());
{- -------------------------------------------
(1.1.1) (トレース出力) (See: EventMark)
---------------------------------------- -}
EventMark em("Executing VM operation: %s", vm_operation()->name());
{- -------------------------------------------
(1.1.1) (assert)
---------------------------------------- -}
assert(_cur_vm_operation != NULL, "we should have found an operation to execute");
{- -------------------------------------------
(1.1.1) もし VMThreadHintNoPreempt オプションが指定されていれば,
VM_Operation 実行中に OS にコンテキストスイッチされないよう,
OS に対して time slice を多めに与えてくれるように要望を出しておく.
(See: VMThreadHintNoPreempt)
---------------------------------------- -}
// Give the VM thread an extra quantum. Jobs tend to be bursty and this
// helps the VM thread to finish up the job.
// FIXME: When this is enabled and there are many threads, this can degrade
// performance significantly.
if( VMThreadHintNoPreempt )
os::hint_no_preempt();
{- -------------------------------------------
(1.1.1) (以下は, safepoint 停止が必要なケースの処理.
SafepointSynchronize::begin() と SafepointSynchronize::end() で safepoint 停止させ,
その中で VMThread::evaluate_operation() による VM_Operation の実行処理を行う.
なお, この場合は, 上で書いたように safepoint を要求する VM_Operation を全部まとめて実行している.
(safepoint 停止する回数を減らすため))
---------------------------------------- -}
// If we are at a safepoint we will evaluate all the operations that
// follow that also require a safepoint
if (_cur_vm_operation->evaluate_at_safepoint()) {
{- -------------------------------------------
(1.1.1.1) safepoint 停止するケースでは GC 処理が行われるかもしれないため,
実行予定の VM_Operation オブジェクトを _drain_list フィールドに登録しておく.
---------------------------------------- -}
_vm_queue->set_drain_list(safepoint_ops); // ensure ops can be scanned
{- -------------------------------------------
(1.1.1.1) SafepointSynchronize::begin() を呼び出す.
(ここからが safepoint 内での処理)
---------------------------------------- -}
SafepointSynchronize::begin();
{- -------------------------------------------
(1.1.1.1) VMThread::evaluate_operation() で取得した VM_Operation を実行.
---------------------------------------- -}
evaluate_operation(_cur_vm_operation);
{- -------------------------------------------
(1.1.1.1) safepoint で実行しないといけない他の VM_Operation (= 上で取得した safepoint_ops の中身) も全部実行する.
---------------------------------------- -}
// now process all queued safepoint ops, iteratively draining
// the queue until there are none left
do {
_cur_vm_operation = safepoint_ops;
if (_cur_vm_operation != NULL) {
do {
// evaluate_operation deletes the op object so we have
// to grab the next op now
VM_Operation* next = _cur_vm_operation->next();
_vm_queue->set_drain_list(next);
evaluate_operation(_cur_vm_operation);
_cur_vm_operation = next;
if (PrintSafepointStatistics) {
SafepointSynchronize::inc_vmop_coalesced_count();
}
} while (_cur_vm_operation != NULL);
}
{- -------------------------------------------
(1.1.1.1) (なお, 上の do..while ループで一応全部実行したはずだが,
排他的に処理しているわけではない(ロックは取っていない)ので, 他のスレッドによって新しく追加された恐れはある.
なので, safepoint 停止する回数を減らすために, 以下でもう一度チェックしている.)
---------------------------------------- -}
// There is a chance that a thread enqueued a safepoint op
// since we released the op-queue lock and initiated the safepoint.
// So we drain the queue again if there is anything there, as an
// optimization to try and reduce the number of safepoints.
// As the safepoint synchronizes us with JavaThreads we will see
// any enqueue made by a JavaThread, but the peek will not
// necessarily detect a concurrent enqueue by a GC thread, but
// that simply means the op will wait for the next major cycle of the
// VMThread - just as it would if the GC thread lost the race for
// the lock.
if (_vm_queue->peek_at_safepoint_priority()) {
// must hold lock while draining queue
MutexLockerEx mu_queue(VMOperationQueue_lock,
Mutex::_no_safepoint_check_flag);
safepoint_ops = _vm_queue->drain_at_safepoint_priority();
} else {
safepoint_ops = NULL;
}
} while(safepoint_ops != NULL);
{- -------------------------------------------
(1.1.1.1) safepoint 処理が終わったので, _drain_list フィールドを元に戻す.
---------------------------------------- -}
_vm_queue->set_drain_list(NULL);
{- -------------------------------------------
(1.1.1.1) 最後に SafepointSynchronize::end() を呼び出す.
(ここまでが safepoint 内での処理)
---------------------------------------- -}
// Complete safepoint synchronization
SafepointSynchronize::end();
{- -------------------------------------------
(1.1.1) (ここまでが, Safepoint 停止が必要なケースの処理)
---------------------------------------- -}
{- -------------------------------------------
(1.1.1) (以下は, Safepoint 停止が不要なケースの処理.
このまま VMThread::evaluate_operation() を呼び出す.
なお, TraceLongCompiles オプションが指定されている場合には(トレース出力)処理も行っている)
---------------------------------------- -}
} else { // not a safepoint operation
if (TraceLongCompiles) {
elapsedTimer t;
t.start();
evaluate_operation(_cur_vm_operation);
t.stop();
double secs = t.seconds();
if (secs * 1e3 > LongCompileThreshold) {
// XXX - _cur_vm_operation should not be accessed after
// the completed count has been incremented; the waiting
// thread may have already freed this memory.
tty->print_cr("vm %s: %3.7f secs]", _cur_vm_operation->name(), secs);
}
} else {
evaluate_operation(_cur_vm_operation);
}
{- -------------------------------------------
(1.1.1.1) _cur_vm_operation の値をリセットしておく
---------------------------------------- -}
_cur_vm_operation = NULL;
}
}
{- -------------------------------------------
(1.1) (ここまでが, 取得した VM_Operation オブジェクトを実際に実行する処理)
---------------------------------------- -}
{- -------------------------------------------
(1.1) VM_Operation の完了を待っている JavaThread がいるかもしれないので, notify_all() しておく.
(See: VMThread::execute())
---------------------------------------- -}
//
// Notify (potential) waiting Java thread(s) - lock without safepoint
// check so that sneaking is not possible
{ MutexLockerEx mu(VMOperationRequest_lock,
Mutex::_no_safepoint_check_flag);
VMOperationRequest_lock->notify_all();
}
{- -------------------------------------------
(1.1) 最後に, 少なくともある程度の時間間隔で Safepoint が行われるよう,
SafepointSynchronize::is_cleanup_needed() を呼んで
Safepoint 停止が必要かどうかを確認しておく.
SafepointSynchronize::is_cleanup_needed() が true であり, かつ
SafepointSynchronize::last_non_safepoint_interval() で取得した値が
GuaranteedSafepointInterval オプションの値を超えていたら,
ここで SafepointSynchronize::begin() と SafepointSynchronize::end() を呼び出す.
(ただし, GuaranteedSafepointInterval が 0 の場合は, この処理は行わない)
(なお, デバッグ用の SafepointALot オプションが指定されている場合は,
SafepointSynchronize::is_cleanup_needed() さえ true であれば,
SafepointSynchronize::last_non_safepoint_interval() や GuaranteedSafepointInterval の値に寄らず
Safepoint 停止処理が行われる.)
---------------------------------------- -}
//
// We want to make sure that we get to a safepoint regularly.
//
if (SafepointALot || SafepointSynchronize::is_cleanup_needed()) {
long interval = SafepointSynchronize::last_non_safepoint_interval();
bool max_time_exceeded = GuaranteedSafepointInterval != 0 && (interval > GuaranteedSafepointInterval);
if (SafepointALot || max_time_exceeded) {
HandleMark hm(VMThread::vm_thread());
SafepointSynchronize::begin();
SafepointSynchronize::end();
}
}
{- -------------------------------------------
(1) (以上の処理を無限ループで繰り返す)
---------------------------------------- -}
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.