hotspot/src/share/vm/prims/jvmtiEventController.cpp
// Compute truly enabled events - meaning if the event can and could be
// sent. An event is truly enabled if it is user enabled on the thread
// or globally user enabled, but only if there is a callback or event hook
// for it and, for field watch and frame pop, one has been set.
// Compute if truly enabled, per thread, per environment, per combination
// (thread x environment), and overall. These merges are true if any is true.
// True per thread if some environment has callback set and the event is globally
// enabled or enabled for this thread.
// True per environment if the callback is set and the event is globally
// enabled in this environment or enabled for any thread in this environment.
// True per combination if the environment has the callback set and the
// event is globally enabled in this environment or the event is enabled
// for this thread and environment.
//
// All states transitions dependent on these transitions are also handled here.
void
JvmtiEventControllerPrivate::recompute_enabled() {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");
{- -------------------------------------------
(1) 現在の truly enabled event 設定を取得.
---------------------------------------- -}
// event enabled for any thread in any environment
jlong was_any_env_thread_enabled = JvmtiEventController::_universal_global_event_enabled.get_bits();
{- -------------------------------------------
(1) (変数宣言など)
(any_env_thread_enabled は新しい truly enabled event の計算結果を格納する変数)
---------------------------------------- -}
jlong any_env_thread_enabled = 0;
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
EC_TRACE(("JVMTI [-] # recompute enabled - before %llx", was_any_env_thread_enabled));
{- -------------------------------------------
(1) (以降で, 新しい truly enabled event を計算する)
---------------------------------------- -}
// compute non-thread-filters events.
// This must be done separately from thread-filtered events, since some
// events can occur before any threads exist.
{- -------------------------------------------
(1.1) 全ての JvmtiEnvBase オブジェクトをたどり,
各 JVMTI environment に対して JvmtiEventControllerPrivate::recompute_env_enabled() を呼び出す.
そして, その結果を any_env_thread_enabled に足し込んでいく.
---------------------------------------- -}
JvmtiEnvIterator it;
for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
any_env_thread_enabled |= recompute_env_enabled(env);
}
{- -------------------------------------------
(1.1) もし, これまではどの thread filtered events (各スレッドごとの処理に同期して発生する event) も有効ではなかったのに
今回の更新で thread filtered events が1つでも有効になっていたら,
各 JavaThread に対して (まだ作られていなければ) JvmtiThreadState を作成する処理を行う.
(具体的にどれが thread filtered events かは THREAD_FILTERED_EVENT_BITS の定義を参照.
なお, 非 thread filtered event だけを集めた GLOBAL_EVENT_BITS という bit mask もある.
参考: 非 thread filtered event の例
* THREAD_START_BIT,
* CLASS_FILE_LOAD_HOOK_BIT
* VM_START_BIT, VM_INIT_BIT, VM_DEATH_BIT,
* NATIVE_METHOD_BIND_BIT,
* DYNAMIC_CODE_GENERATED_BIT )
---------------------------------------- -}
// We need to create any missing jvmti_thread_state if there are globally set thread
// filtered events and there weren't last time
if ( (any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) != 0 &&
(was_any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) == 0) {
assert(JvmtiEnv::is_vm_live() || (JvmtiEnv::get_phase()==JVMTI_PHASE_START),
"thread filtered events should not be enabled when VM not in start or live phase");
{
MutexLocker mu(Threads_lock); //hold the Threads_lock for the iteration
for (JavaThread *tp = Threads::first(); tp != NULL; tp = tp->next()) {
// state_for_while_locked() makes tp->is_exiting() check
JvmtiThreadState::state_for_while_locked(tp); // create the thread state if missing
}
}// release Threads_lock
}
{- -------------------------------------------
(1.1) 全ての JvmtiThreadState をたどり, JvmtiEventControllerPrivate::recompute_thread_enabled() を呼び出す.
そして, その結果を any_env_thread_enabled に足し込んでいく.
---------------------------------------- -}
// compute and set thread-filtered events
for (JvmtiThreadState *state = JvmtiThreadState::first(); state != NULL; state = state->next()) {
any_env_thread_enabled |= recompute_thread_enabled(state);
}
{- -------------------------------------------
(1) もし新しい truly enabled event が古いものと異なれば,
以下の if ブロック内でその変更を反映させる処理を行う.
(行う処理は主に JvmtiExport::set_should_post_*() を呼び出すことのみ.
なお, JvmtiExport::set_should_post_*() はソースコード上での定義位置が分かりにくいので注意 (See: JvmtiExport))
---------------------------------------- -}
// set universal state (across all envs and threads)
jlong delta = any_env_thread_enabled ^ was_any_env_thread_enabled;
if (delta != 0) {
{- -------------------------------------------
(1.1) JvmtiExport::set_should_post_*() を呼び出す
---------------------------------------- -}
JvmtiExport::set_should_post_field_access((any_env_thread_enabled & FIELD_ACCESS_BIT) != 0);
JvmtiExport::set_should_post_field_modification((any_env_thread_enabled & FIELD_MODIFICATION_BIT) != 0);
JvmtiExport::set_should_post_class_load((any_env_thread_enabled & CLASS_LOAD_BIT) != 0);
JvmtiExport::set_should_post_class_file_load_hook((any_env_thread_enabled & CLASS_FILE_LOAD_HOOK_BIT) != 0);
JvmtiExport::set_should_post_native_method_bind((any_env_thread_enabled & NATIVE_METHOD_BIND_BIT) != 0);
JvmtiExport::set_should_post_dynamic_code_generated((any_env_thread_enabled & DYNAMIC_CODE_GENERATED_BIT) != 0);
JvmtiExport::set_should_post_data_dump((any_env_thread_enabled & DATA_DUMP_BIT) != 0);
JvmtiExport::set_should_post_class_prepare((any_env_thread_enabled & CLASS_PREPARE_BIT) != 0);
JvmtiExport::set_should_post_class_unload((any_env_thread_enabled & CLASS_UNLOAD_BIT) != 0);
JvmtiExport::set_should_post_monitor_contended_enter((any_env_thread_enabled & MONITOR_CONTENDED_ENTER_BIT) != 0);
JvmtiExport::set_should_post_monitor_contended_entered((any_env_thread_enabled & MONITOR_CONTENDED_ENTERED_BIT) != 0);
JvmtiExport::set_should_post_monitor_wait((any_env_thread_enabled & MONITOR_WAIT_BIT) != 0);
JvmtiExport::set_should_post_monitor_waited((any_env_thread_enabled & MONITOR_WAITED_BIT) != 0);
JvmtiExport::set_should_post_garbage_collection_start((any_env_thread_enabled & GARBAGE_COLLECTION_START_BIT) != 0);
JvmtiExport::set_should_post_garbage_collection_finish((any_env_thread_enabled & GARBAGE_COLLECTION_FINISH_BIT) != 0);
JvmtiExport::set_should_post_object_free((any_env_thread_enabled & OBJECT_FREE_BIT) != 0);
JvmtiExport::set_should_post_resource_exhausted((any_env_thread_enabled & RESOURCE_EXHAUSTED_BIT) != 0);
JvmtiExport::set_should_post_compiled_method_load((any_env_thread_enabled & COMPILED_METHOD_LOAD_BIT) != 0);
JvmtiExport::set_should_post_compiled_method_unload((any_env_thread_enabled & COMPILED_METHOD_UNLOAD_BIT) != 0);
JvmtiExport::set_should_post_vm_object_alloc((any_env_thread_enabled & VM_OBJECT_ALLOC_BIT) != 0);
// need this if we want thread events or we need them to init data
JvmtiExport::set_should_post_thread_life((any_env_thread_enabled & NEED_THREAD_LIFE_EVENTS) != 0);
{- -------------------------------------------
(1.1) SINGLE_STEP_BIT に変更が有った場合には, VM_ChangeSingleStep を実行して SingleStep 状態の ON/OFF を行う.
(ただし, この処理は JVMTI_PHASE_LIVE の場合にしか行わない.
JVMTI_PHASE_DEAD であれば無視するだけ. それ以外の phase であれば assert failure.)
---------------------------------------- -}
// If single stepping is turned on or off, execute the VM op to change it.
if (delta & SINGLE_STEP_BIT) {
switch (JvmtiEnv::get_phase()) {
case JVMTI_PHASE_DEAD:
// If the VM is dying we can't execute VM ops
break;
case JVMTI_PHASE_LIVE: {
VM_ChangeSingleStep op((any_env_thread_enabled & SINGLE_STEP_BIT) != 0);
VMThread::execute(&op);
break;
}
default:
assert(false, "should never come here before live phase");
break;
}
}
{- -------------------------------------------
(1.1) 新しい truly enabled event を
JvmtiEventController::_universal_global_event_enabled にキャッシュしておく.
---------------------------------------- -}
// set global truly enabled, that is, any thread in any environment
JvmtiEventController::_universal_global_event_enabled.set_bits(any_env_thread_enabled);
{- -------------------------------------------
(1.1) JvmtiExport::set_should_post_*() を呼び出す
---------------------------------------- -}
// set global should_post_on_exceptions
JvmtiExport::set_should_post_on_exceptions((any_env_thread_enabled & SHOULD_POST_ON_EXCEPTIONS_BITS) != 0);
}
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
EC_TRACE(("JVMTI [-] # recompute enabled - after %llx", any_env_thread_enabled));
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.