void JvmtiEventControllerPrivate::enter_interp_only_mode(JvmtiThreadState *state) { EC_TRACE(("JVMTI [%s] # Entering interpreter only mode", JvmtiTrace::safe_get_thread_name(state->get_thread()))); VM_EnterInterpOnlyMode op(state); VMThread::execute(&op); }
void JvmtiEventControllerPrivate::clear_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) { EC_TRACE(("JVMTI [%s] # clear frame pop - frame=%d", JvmtiTrace::safe_get_thread_name(ets->get_thread()), fpop.frame_number() )); ets->get_frame_pops()->clear(fpop); recompute_thread_enabled(ets->get_thread()->jvmti_thread_state()); }
void JvmtiEventControllerPrivate::thread_ended(JavaThread *thread) { // Removes the JvmtiThreadState associated with the specified thread. // May be called after all environments have been disposed. assert(JvmtiThreadState_lock->is_locked(), "sanity check"); EC_TRACE(("JVMTI [%s] # thread ended", JvmtiTrace::safe_get_thread_name(thread))); JvmtiThreadState *state = thread->jvmti_thread_state(); assert(state != NULL, "else why are we here?"); delete state; }
void JvmtiEventControllerPrivate::clear_to_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) { int cleared_cnt = ets->get_frame_pops()->clear_to(fpop); EC_TRACE(("JVMTI [%s] # clear to frame pop - frame=%d, count=%d", JvmtiTrace::safe_get_thread_name(ets->get_thread()), fpop.frame_number(), cleared_cnt )); if (cleared_cnt > 0) { recompute_thread_enabled(ets->get_thread()->jvmti_thread_state()); } }
void JvmtiEventControllerPrivate::thread_ended(JavaThread *thread) { // Removes the JvmtiThreadState associated with the specified thread. // May be called after all environments have been disposed. EC_TRACE(("JVMTI [%s] # thread ended", JvmtiTrace::safe_get_thread_name(thread))); JvmtiThreadState *state = thread->jvmti_thread_state(); if (state != NULL) { MutexLocker mu(JvmtiThreadState_lock); delete state; } }
void JvmtiEventControllerPrivate::set_extension_event_callback(JvmtiEnvBase *env, jint extension_event_index, jvmtiExtensionEvent callback) { assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); EC_TRACE(("JVMTI [*] # set extension event callback")); // extension events are allocated below JVMTI_MIN_EVENT_TYPE_VAL assert(extension_event_index >= (jint)EXT_MIN_EVENT_TYPE_VAL && extension_event_index <= (jint)EXT_MAX_EVENT_TYPE_VAL, "sanity check"); // As the bits for both standard (jvmtiEvent) and extension // (jvmtiExtEvents) are stored in the same word we cast here to // jvmtiEvent to set/clear the bit for this extension event. jvmtiEvent event_type = (jvmtiEvent)extension_event_index; // Prevent a possible race condition where events are re-enabled by a call to // set event callbacks, where the DisposeEnvironment occurs after the boiler-plate // environment check and before the lock is acquired. // We can safely do the is_valid check now, as JvmtiThreadState_lock is held. bool enabling = (callback != NULL) && (env->is_valid()); env->env_event_enable()->set_user_enabled(event_type, enabling); // update the callback jvmtiExtEventCallbacks* ext_callbacks = env->ext_callbacks(); switch (extension_event_index) { case EXT_EVENT_CLASS_UNLOAD : ext_callbacks->ClassUnload = callback; break; default: ShouldNotReachHere(); } // update the callback enable/disable bit jlong enabled_bits = env->env_event_enable()->_event_callback_enabled.get_bits(); jlong bit_for = JvmtiEventEnabled::bit_for(event_type); if (enabling) { enabled_bits |= bit_for; } else { enabled_bits &= ~bit_for; } env->env_event_enable()->_event_callback_enabled.set_bits(enabled_bits); recompute_enabled(); }
void JvmtiEventControllerPrivate::set_event_callbacks(JvmtiEnvBase *env, const jvmtiEventCallbacks* callbacks, jint size_of_callbacks) { assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); EC_TRACE(("JVMTI [*] # set event callbacks")); env->set_event_callbacks(callbacks, size_of_callbacks); jlong enabled_bits = 0; for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) { jvmtiEvent evt_t = (jvmtiEvent)ei; if (env->has_callback(evt_t)) { enabled_bits |= JvmtiEventEnabled::bit_for(evt_t); } } env->env_event_enable()->_event_callback_enabled.set_bits(enabled_bits); recompute_enabled(); }
void JvmtiEventControllerPrivate::env_dispose(JvmtiEnvBase *env) { assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); EC_TRACE(("JVMTI [*] # env dispose")); // Before the environment is marked disposed, disable all events on this // environment (by zapping the callbacks). As a result, the disposed // environment will not call event handlers. set_event_callbacks(env, NULL, 0); for (jint extension_event_index = EXT_MIN_EVENT_TYPE_VAL; extension_event_index <= EXT_MAX_EVENT_TYPE_VAL; ++extension_event_index) { set_extension_event_callback(env, extension_event_index, NULL); } // Let the environment finish disposing itself. env->env_dispose(); }
void JvmtiEventControllerPrivate::thread_started(JavaThread *thread) { assert(thread->is_Java_thread(), "Must be JavaThread"); assert(thread == Thread::current(), "must be current thread"); assert(JvmtiEnvBase::environments_might_exist(), "to enter event controller, JVM TI environments must exist"); EC_TRACE(("JVMTI [%s] # thread started", JvmtiTrace::safe_get_thread_name(thread))); // if we have any thread filtered events globally enabled, create/update the thread state if ((JvmtiEventController::_universal_global_event_enabled.get_bits() & THREAD_FILTERED_EVENT_BITS) != 0) { MutexLocker mu(JvmtiThreadState_lock); // create the thread state if missing JvmtiThreadState *state = JvmtiThreadState::state_for_while_locked(thread); if (state != NULL) { // skip threads with no JVMTI thread state recompute_thread_enabled(state); } } }
void JvmtiEventControllerPrivate::set_user_enabled(JvmtiEnvBase *env, JavaThread *thread, jvmtiEvent event_type, bool enabled) { assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); EC_TRACE(("JVMTI [%s] # user %s event %s", thread==NULL? "ALL": JvmtiTrace::safe_get_thread_name(thread), enabled? "enabled" : "disabled", JvmtiTrace::event_name(event_type))); if (thread == NULL) { env->env_event_enable()->set_user_enabled(event_type, enabled); } else { // create the thread state (if it didn't exist before) JvmtiThreadState *state = JvmtiThreadState::state_for_while_locked(thread); if (state != NULL) { state->env_thread_state(env)->event_enable()->set_user_enabled(event_type, enabled); } } recompute_enabled(); }
void JvmtiEventControllerPrivate::env_initialize(JvmtiEnvBase *env) { assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); EC_TRACE(("JVMTI [*] # env initialize")); if (JvmtiEnvBase::is_vm_live()) { // if we didn't initialize event info already (this is a late // launched environment), do it now. event_init(); } env->initialize(); // add the JvmtiEnvThreadState to each JvmtiThreadState for (JvmtiThreadState *state = JvmtiThreadState::first(); state != NULL; state = state->next()) { state->add_env(env); assert((JvmtiEnv*)(state->env_thread_state(env)->get_env()) == env, "sanity check"); } JvmtiEventControllerPrivate::recompute_enabled(); }
void JvmtiEventControllerPrivate::event_init() { assert(JvmtiThreadState_lock->is_locked(), "sanity check"); if (_initialized) { return; } EC_TRACE(("JVMTI [-] # VM live")); #ifdef ASSERT // check that our idea and the spec's idea of threaded events match for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) { jlong bit = JvmtiEventEnabled::bit_for((jvmtiEvent)ei); assert(((THREAD_FILTERED_EVENT_BITS & bit) != 0) == JvmtiUtil::event_threaded(ei), "thread filtered event list does not match"); } #endif _initialized = true; }
void JvmtiEventControllerPrivate::change_field_watch(jvmtiEvent event_type, bool added) { int *count_addr; switch (event_type) { case JVMTI_EVENT_FIELD_MODIFICATION: count_addr = (int *)JvmtiExport::get_field_modification_count_addr(); break; case JVMTI_EVENT_FIELD_ACCESS: count_addr = (int *)JvmtiExport::get_field_access_count_addr(); break; default: assert(false, "incorrect event"); return; } EC_TRACE(("JVMTI [-] # change field watch - %s %s count=%d", event_type==JVMTI_EVENT_FIELD_MODIFICATION? "modification" : "access", added? "add" : "remove", *count_addr)); if (added) { (*count_addr)++; if (*count_addr == 1) { recompute_enabled(); } } else { if (*count_addr > 0) { (*count_addr)--; if (*count_addr == 0) { recompute_enabled(); } } else { assert(false, "field watch out of phase"); } } }
// 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() { assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); // event enabled for any thread in any environment jlong was_any_env_thread_enabled = JvmtiEventController::_universal_global_event_enabled.get_bits(); jlong any_env_thread_enabled = 0; EC_TRACE(("JVMTI [-] # recompute enabled - before " UINT64_FORMAT_X, was_any_env_thread_enabled)); // compute non-thread-filters events. // This must be done separately from thread-filtered events, since some // events can occur before any threads exist. JvmtiEnvIterator it; for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) { any_env_thread_enabled |= recompute_env_enabled(env); } // 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 } // compute and set thread-filtered events for (JvmtiThreadState *state = JvmtiThreadState::first(); state != NULL; state = state->next()) { any_env_thread_enabled |= recompute_thread_enabled(state); } // set universal state (across all envs and threads) jlong delta = any_env_thread_enabled ^ was_any_env_thread_enabled; if (delta != 0) { 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); // 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; } } // set global truly enabled, that is, any thread in any environment JvmtiEventController::_universal_global_event_enabled.set_bits(any_env_thread_enabled); // set global should_post_on_exceptions JvmtiExport::set_should_post_on_exceptions((any_env_thread_enabled & SHOULD_POST_ON_EXCEPTIONS_BITS) != 0); } EC_TRACE(("JVMTI [-] # recompute enabled - after " UINT64_FORMAT_X, any_env_thread_enabled)); }
void JvmtiEventControllerPrivate::leave_interp_only_mode(JvmtiThreadState *state) { EC_TRACE(("JVMTI [%s] # Leaving interpreter only mode", JvmtiTrace::safe_get_thread_name(state->get_thread()))); state->leave_interp_only_mode(); }