+++ hotspot/src/share/vm/prims/jvmtiEnvBase.cpp 2009-02-10 11:35:55.000000000 -0800 @@ -38,7 +38,7 @@ bool JvmtiEnvBase::_globally_initialized = false; volatile bool JvmtiEnvBase::_needs_clean_up = false; -jvmtiPhase JvmtiEnvBase::_phase = JVMTI_PHASE_PRIMORDIAL; +volatile jvmtiPhase JvmtiEnvBase::_phase = JVMTI_PHASE_PRIMORDIAL; volatile int JvmtiEnvBase::_dying_thread_env_iteration_count = 0; @@ -1407,4 +1407,3 @@ } } } - +++ hotspot/src/share/vm/prims/jvmtiEnvBase.hpp 2009-02-10 19:39:41.000000000 -0800 @@ -48,11 +48,11 @@ private: - static JvmtiEnvBase* _head_environment; // head of environment list + static JvmtiEnvBase* _head_environment; // head of environment list - static bool _globally_initialized; - static jvmtiPhase _phase; - static volatile int _dying_thread_env_iteration_count; + static bool _globally_initialized; + static volatile jvmtiPhase _phase; + static volatile int _dying_thread_env_iteration_count; public: +++ hotspot/src/share/vm/prims/jvmtiExport.cpp 2009-02-10 19:44:35.000000000 -0800 @@ -36,6 +36,8 @@ #define EVT_TRACE(evt,out) #endif +#define RETURN_IF_PHASE_DEAD() MutexLocker mu(JvmtiPhase_lock); if (JvmtiEnv::get_phase() == JVMTI_PHASE_DEAD) { return; } + /////////////////////////////////////////////////////////////// // @@ -452,6 +454,7 @@ // void JvmtiExport::post_raw_breakpoint(JavaThread *thread, methodOop method, address location) { + RETURN_IF_PHASE_DEAD(); HandleMark hm(thread); methodHandle mh(thread, method); @@ -726,26 +729,28 @@ } void JvmtiExport::post_vm_death() { - EVT_TRIG_TRACE(JVMTI_EVENT_VM_DEATH, ("JVMTI Trg VM death event triggered" )); + { + MutexLocker mu(JvmtiPhase_lock); - JvmtiEnvIterator it; - for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) { - if (env->is_enabled(JVMTI_EVENT_VM_DEATH)) { - EVT_TRACE(JVMTI_EVENT_VM_DEATH, ("JVMTI Evt VM death event sent" )); - - JavaThread *thread = JavaThread::current(); - JvmtiEventMark jem(thread); - JvmtiJavaThreadEventTransition jet(thread); - jvmtiEventVMDeath callback = env->callbacks()->VMDeath; - if (callback != NULL) { - (*callback)(env->jvmti_external(), jem.jni_env()); + EVT_TRIG_TRACE(JVMTI_EVENT_VM_DEATH, ("JVMTI Trg VM death event triggered" )); + + JvmtiEnvIterator it; + for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) { + if (env->is_enabled(JVMTI_EVENT_VM_DEATH)) { + EVT_TRACE(JVMTI_EVENT_VM_DEATH, ("JVMTI Evt VM death event sent" )); + JavaThread *thread = JavaThread::current(); + JvmtiEventMark jem(thread); + JvmtiJavaThreadEventTransition jet(thread); + jvmtiEventVMDeath callback = env->callbacks()->VMDeath; + if (callback != NULL) { + (*callback)(env->jvmti_external(), jem.jni_env()); + } } } + JvmtiEnvBase::set_phase(JVMTI_PHASE_DEAD); + JvmtiEventController::vm_death(); } - JvmtiEnvBase::set_phase(JVMTI_PHASE_DEAD); - JvmtiEventController::vm_death(); - // Send any Agent_OnUnload notifications const char *on_unload_symbols[] = AGENT_ONUNLOAD_SYMBOLS; extern struct JavaVM_ main_vm; @@ -770,6 +775,7 @@ void JvmtiExport::post_class_load(JavaThread *thread, klassOop klass) { + RETURN_IF_PHASE_DEAD(); HandleMark hm(thread); KlassHandle kh(thread, klass); @@ -799,6 +805,7 @@ void JvmtiExport::post_class_prepare(JavaThread *thread, klassOop klass) { + RETURN_IF_PHASE_DEAD(); HandleMark hm(thread); KlassHandle kh(thread, klass); @@ -827,6 +834,7 @@ } void JvmtiExport::post_class_unload(klassOop klass) { + RETURN_IF_PHASE_DEAD(); Thread *thread = Thread::current(); HandleMark hm(thread); KlassHandle kh(thread, klass); @@ -874,6 +882,7 @@ void JvmtiExport::post_thread_start(JavaThread *thread) { + RETURN_IF_PHASE_DEAD(); assert(thread->thread_state() == _thread_in_vm, "must be in vm state"); EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Trg Thread Start event triggered", @@ -904,6 +913,7 @@ void JvmtiExport::post_thread_end(JavaThread *thread) { + RETURN_IF_PHASE_DEAD(); EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Trg Thread End event triggered", JvmtiTrace::safe_get_thread_name(thread))); @@ -935,6 +945,7 @@ } void JvmtiExport::post_object_free(JvmtiEnv* env, jlong tag) { + RETURN_IF_PHASE_DEAD(); assert(SafepointSynchronize::is_at_safepoint(), "must be executed at safepoint"); assert(env->is_enabled(JVMTI_EVENT_OBJECT_FREE), "checking"); @@ -948,6 +959,7 @@ } void JvmtiExport::post_resource_exhausted(jint resource_exhausted_flags, const char* description) { + RETURN_IF_PHASE_DEAD(); EVT_TRIG_TRACE(JVMTI_EVENT_RESOURCE_EXHAUSTED, ("JVMTI Trg resource exhausted event triggered" )); JvmtiEnvIterator it; @@ -968,6 +980,7 @@ } void JvmtiExport::post_method_entry(JavaThread *thread, methodOop method, frame current_frame) { + RETURN_IF_PHASE_DEAD(); HandleMark hm(thread); methodHandle mh(thread, method); @@ -1006,6 +1019,7 @@ } void JvmtiExport::post_method_exit(JavaThread *thread, methodOop method, frame current_frame) { + RETURN_IF_PHASE_DEAD(); HandleMark hm(thread); methodHandle mh(thread, method); @@ -1101,6 +1115,7 @@ // Todo: inline this for optimization void JvmtiExport::post_single_step(JavaThread *thread, methodOop method, address location) { + RETURN_IF_PHASE_DEAD(); HandleMark hm(thread); methodHandle mh(thread, method); @@ -1134,6 +1149,7 @@ void JvmtiExport::post_exception_throw(JavaThread *thread, methodOop method, address location, oop exception) { + RETURN_IF_PHASE_DEAD(); HandleMark hm(thread); methodHandle mh(thread, method); Handle exception_handle(thread, exception); @@ -1309,6 +1325,7 @@ void JvmtiExport::post_field_access_by_jni(JavaThread *thread, oop obj, klassOop klass, jfieldID fieldID, bool is_static) { + RETURN_IF_PHASE_DEAD(); // We must be called with a Java context in order to provide reasonable // values for the klazz, method, and location fields. The callers of this // function don't make the call unless there is a Java context. @@ -1339,6 +1356,7 @@ void JvmtiExport::post_field_access(JavaThread *thread, methodOop method, address location, KlassHandle field_klass, Handle object, jfieldID field) { + RETURN_IF_PHASE_DEAD(); HandleMark hm(thread); methodHandle mh(thread, method); @@ -1406,6 +1424,7 @@ void JvmtiExport::post_field_modification_by_jni(JavaThread *thread, oop obj, klassOop klass, jfieldID fieldID, bool is_static, char sig_type, jvalue *value) { + RETURN_IF_PHASE_DEAD(); // We must be called with a Java context in order to provide reasonable // values for the klazz, method, and location fields. The callers of this // function don't make the call unless there is a Java context. @@ -1438,6 +1457,7 @@ void JvmtiExport::post_raw_field_modification(JavaThread *thread, methodOop method, address location, KlassHandle field_klass, Handle object, jfieldID field, char sig_type, jvalue *value) { + RETURN_IF_PHASE_DEAD(); if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'C' || sig_type == 'S') { // 'I' instructions are used for byte, char, short and int. @@ -1496,6 +1516,7 @@ void JvmtiExport::post_field_modification(JavaThread *thread, methodOop method, address location, KlassHandle field_klass, Handle object, jfieldID field, char sig_type, jvalue *value_ptr) { + RETURN_IF_PHASE_DEAD(); HandleMark hm(thread); methodHandle mh(thread, method); @@ -1689,6 +1710,7 @@ unsigned char **end_ptr, unsigned char **cached_data_ptr, jint *cached_length_ptr) { + RETURN_IF_PHASE_DEAD(); JvmtiClassFileLoadHookPoster poster(h_name, class_loader, h_protection_domain, data_ptr, end_ptr, @@ -1698,6 +1720,7 @@ } void JvmtiExport::post_native_method_bind(methodOop method, address* function_ptr) { + RETURN_IF_PHASE_DEAD(); JavaThread* thread = JavaThread::current(); assert(thread->thread_state() == _thread_in_vm, "must be in vm state"); @@ -1729,6 +1752,7 @@ void JvmtiExport::post_compiled_method_load(nmethod *nm) { + RETURN_IF_PHASE_DEAD(); // If there are pending CompiledMethodUnload events then these are // posted before this CompiledMethodLoad event. We "lock" the nmethod and // maintain a handle to the methodOop to ensure that the nmethod isn't @@ -1773,6 +1797,7 @@ const void *code_begin, const jint map_length, const jvmtiAddrLocationMap* map) { + RETURN_IF_PHASE_DEAD(); JavaThread* thread = JavaThread::current(); EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD, ("JVMTI [%s] method compile load event triggered (by GenerateEvents)", @@ -1831,6 +1856,7 @@ } void JvmtiExport::post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) { + RETURN_IF_PHASE_DEAD(); // In theory everyone coming thru here is in_vm but we need to be certain // because a callee will do a vm->native transition ThreadInVMfromUnknown __tiv; @@ -1852,6 +1878,7 @@ void JvmtiExport::post_dynamic_code_generated(JvmtiEnv* env, const char *name, const void *code_begin, const void *code_end) { + RETURN_IF_PHASE_DEAD(); JavaThread* thread = JavaThread::current(); EVT_TRIG_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED, ("JVMTI [%s] dynamic code generated event triggered (by GenerateEvents)", @@ -1906,6 +1933,7 @@ } void JvmtiExport::post_garbage_collection_finish() { + RETURN_IF_PHASE_DEAD(); Thread *thread = Thread::current(); // this event is posted from VM-Thread. EVT_TRIG_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, ("JVMTI [%s] garbage collection finish event triggered", @@ -1927,6 +1955,7 @@ } void JvmtiExport::post_garbage_collection_start() { + RETURN_IF_PHASE_DEAD(); Thread* thread = Thread::current(); // this event is posted from vm-thread. EVT_TRIG_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_START, ("JVMTI [%s] garbage collection start event triggered", @@ -1948,6 +1977,7 @@ } void JvmtiExport::post_data_dump() { + RETURN_IF_PHASE_DEAD(); Thread *thread = Thread::current(); EVT_TRIG_TRACE(JVMTI_EVENT_DATA_DUMP_REQUEST, ("JVMTI [%s] data dump request event triggered", @@ -1969,6 +1999,7 @@ } void JvmtiExport::post_monitor_contended_enter(JavaThread *thread, ObjectMonitor *obj_mntr) { + RETURN_IF_PHASE_DEAD(); oop object = (oop)obj_mntr->object(); if (!ServiceUtil::visible_oop(object)) { // Ignore monitor contended enter for vm internal object. @@ -2004,6 +2035,7 @@ } void JvmtiExport::post_monitor_contended_entered(JavaThread *thread, ObjectMonitor *obj_mntr) { + RETURN_IF_PHASE_DEAD(); oop object = (oop)obj_mntr->object(); if (!ServiceUtil::visible_oop(object)) { // Ignore monitor contended entered for vm internal object. @@ -2040,6 +2072,7 @@ void JvmtiExport::post_monitor_wait(JavaThread *thread, oop object, jlong timeout) { + RETURN_IF_PHASE_DEAD(); JvmtiThreadState *state = thread->jvmti_thread_state(); if (state == NULL) { return; @@ -2071,6 +2104,7 @@ } void JvmtiExport::post_monitor_waited(JavaThread *thread, ObjectMonitor *obj_mntr, jboolean timed_out) { + RETURN_IF_PHASE_DEAD(); oop object = (oop)obj_mntr->object(); if (!ServiceUtil::visible_oop(object)) { // Ignore monitor waited for vm internal object. @@ -2108,6 +2142,7 @@ void JvmtiExport::post_vm_object_alloc(JavaThread *thread, oop object) { + RETURN_IF_PHASE_DEAD(); EVT_TRIG_TRACE(JVMTI_EVENT_VM_OBJECT_ALLOC, ("JVMTI [%s] Trg vm object alloc triggered", JvmtiTrace::safe_get_thread_name(thread))); if (object == NULL) { @@ -2506,5 +2541,3 @@ // Notify heap/object tagging support JvmtiTagMap::gc_epilogue(_full); } - - +++ hotspot/src/share/vm/runtime/mutexLocker.cpp 2009-02-10 19:40:31.000000000 -0800 @@ -44,6 +44,7 @@ Monitor* JNICritical_lock = NULL; Mutex* JvmtiThreadState_lock = NULL; Monitor* JvmtiPendingEvent_lock = NULL; +Mutex* JvmtiPhase_lock = NULL; Mutex* Heap_lock = NULL; Mutex* ExpandHeap_lock = NULL; Mutex* AdapterHandlerLibrary_lock = NULL; @@ -215,6 +216,7 @@ def(JvmtiThreadState_lock , Mutex , nonleaf+2, false); // Used by JvmtiThreadState/JvmtiEventController def(JvmtiPendingEvent_lock , Monitor, nonleaf, false); // Used by JvmtiCodeBlobEvents + def(JvmtiPhase_lock , Mutex , nonleaf+5, false); // Used by JvmtiExport to protect against dead posts def(Management_lock , Mutex , nonleaf+2, false); // used for JVM management def(Compile_lock , Mutex , nonleaf+3, true ); @@ -261,4 +263,3 @@ } if (none) st->print_cr("None"); } - +++ hotspot/src/share/vm/runtime/mutexLocker.hpp 2009-02-09 23:40:14.000000000 -0800 @@ -41,6 +41,7 @@ extern Monitor* JNICritical_lock; // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in extern Mutex* JvmtiThreadState_lock; // a lock on modification of JVMTI thread data extern Monitor* JvmtiPendingEvent_lock; // a lock on the JVMTI pending events list +extern Mutex* JvmtiPhase_lock; // a lock on the JVMTI phase extern Mutex* Heap_lock; // a lock on the heap extern Mutex* ExpandHeap_lock; // a lock on expanding the heap extern Mutex* AdapterHandlerLibrary_lock; // a lock on the AdapterHandlerLibrary @@ -326,4 +327,3 @@ }; #endif -