aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/prims
diff options
context:
space:
mode:
authortrims <none@none>2009-03-12 18:16:36 -0700
committertrims <none@none>2009-03-12 18:16:36 -0700
commitbe223741e196a9674309e0ad6f7a6ee80d4a708c (patch)
tree7d1460f138a00c594cb7dd4097b6971a2c686eb4 /src/share/vm/prims
parent2ccc9bd9f66f568de9d973a2bb916c40058c63fa (diff)
parent31afc3d8e2d634535d9a254cc30e88724e99cb07 (diff)
downloadjdk8u_hotspot-be223741e196a9674309e0ad6f7a6ee80d4a708c.tar.gz
Merge
Diffstat (limited to 'src/share/vm/prims')
-rw-r--r--src/share/vm/prims/jvmtiEnv.cpp21
-rw-r--r--src/share/vm/prims/jvmtiEnvBase.cpp38
-rw-r--r--src/share/vm/prims/jvmtiEnvBase.hpp2
-rw-r--r--src/share/vm/prims/jvmtiEventController.cpp6
-rw-r--r--src/share/vm/prims/jvmtiExport.cpp6
-rw-r--r--src/share/vm/prims/jvmtiImpl.cpp29
-rw-r--r--src/share/vm/prims/jvmtiImpl.hpp2
-rw-r--r--src/share/vm/prims/jvmtiRedefineClasses.cpp31
-rw-r--r--src/share/vm/prims/jvmtiRedefineClassesTrace.hpp4
-rw-r--r--src/share/vm/prims/jvmtiThreadState.hpp7
10 files changed, 121 insertions, 25 deletions
diff --git a/src/share/vm/prims/jvmtiEnv.cpp b/src/share/vm/prims/jvmtiEnv.cpp
index a19c48972..95977f009 100644
--- a/src/share/vm/prims/jvmtiEnv.cpp
+++ b/src/share/vm/prims/jvmtiEnv.cpp
@@ -99,6 +99,9 @@ JvmtiEnv::SetThreadLocalStorage(JavaThread* java_thread, const void* data) {
}
// otherwise, create the state
state = JvmtiThreadState::state_for(java_thread);
+ if (state == NULL) {
+ return JVMTI_ERROR_THREAD_NOT_ALIVE;
+ }
}
state->env_thread_state(this)->set_agent_thread_local_storage_data((void*)data);
return JVMTI_ERROR_NONE;
@@ -1308,6 +1311,9 @@ JvmtiEnv::GetFrameCount(JavaThread* java_thread, jint* count_ptr) {
// retrieve or create JvmtiThreadState.
JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread);
+ if (state == NULL) {
+ return JVMTI_ERROR_THREAD_NOT_ALIVE;
+ }
uint32_t debug_bits = 0;
if (is_thread_fully_suspended(java_thread, true, &debug_bits)) {
err = get_frame_count(state, count_ptr);
@@ -1329,6 +1335,12 @@ JvmtiEnv::PopFrame(JavaThread* java_thread) {
HandleMark hm(current_thread);
uint32_t debug_bits = 0;
+ // retrieve or create the state
+ JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread);
+ if (state == NULL) {
+ return JVMTI_ERROR_THREAD_NOT_ALIVE;
+ }
+
// Check if java_thread is fully suspended
if (!is_thread_fully_suspended(java_thread, true /* wait for suspend completion */, &debug_bits)) {
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
@@ -1399,9 +1411,6 @@ JvmtiEnv::PopFrame(JavaThread* java_thread) {
// It's fine to update the thread state here because no JVMTI events
// shall be posted for this PopFrame.
- // retreive or create the state
- JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread);
-
state->update_for_pop_top_frame();
java_thread->set_popframe_condition(JavaThread::popframe_pending_bit);
// Set pending step flag for this popframe and it is cleared when next
@@ -1445,6 +1454,11 @@ JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) {
ResourceMark rm;
uint32_t debug_bits = 0;
+ JvmtiThreadState *state = JvmtiThreadState::state_for(java_thread);
+ if (state == NULL) {
+ return JVMTI_ERROR_THREAD_NOT_ALIVE;
+ }
+
if (!JvmtiEnv::is_thread_fully_suspended(java_thread, true, &debug_bits)) {
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
}
@@ -1464,7 +1478,6 @@ JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) {
assert(vf->frame_pointer() != NULL, "frame pointer mustn't be NULL");
- JvmtiThreadState *state = JvmtiThreadState::state_for(java_thread);
int frame_number = state->count_frames() - depth;
state->env_thread_state(this)->set_frame_pop(frame_number);
diff --git a/src/share/vm/prims/jvmtiEnvBase.cpp b/src/share/vm/prims/jvmtiEnvBase.cpp
index 3152e91c3..c0c98f01e 100644
--- a/src/share/vm/prims/jvmtiEnvBase.cpp
+++ b/src/share/vm/prims/jvmtiEnvBase.cpp
@@ -94,6 +94,35 @@ JvmtiEnvBase::initialize() {
}
+bool
+JvmtiEnvBase::is_valid() {
+ jint value = 0;
+
+ // This object might not be a JvmtiEnvBase so we can't assume
+ // the _magic field is properly aligned. Get the value in a safe
+ // way and then check against JVMTI_MAGIC.
+
+ switch (sizeof(_magic)) {
+ case 2:
+ value = Bytes::get_native_u2((address)&_magic);
+ break;
+
+ case 4:
+ value = Bytes::get_native_u4((address)&_magic);
+ break;
+
+ case 8:
+ value = Bytes::get_native_u8((address)&_magic);
+ break;
+
+ default:
+ guarantee(false, "_magic field is an unexpected size");
+ }
+
+ return value == JVMTI_MAGIC;
+}
+
+
JvmtiEnvBase::JvmtiEnvBase() : _env_event_enable() {
_env_local_storage = NULL;
_tag_map = NULL;
@@ -1322,6 +1351,12 @@ JvmtiEnvBase::force_early_return(JavaThread* java_thread, jvalue value, TosState
HandleMark hm(current_thread);
uint32_t debug_bits = 0;
+ // retrieve or create the state
+ JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread);
+ if (state == NULL) {
+ return JVMTI_ERROR_THREAD_NOT_ALIVE;
+ }
+
// Check if java_thread is fully suspended
if (!is_thread_fully_suspended(java_thread,
true /* wait for suspend completion */,
@@ -1329,9 +1364,6 @@ JvmtiEnvBase::force_early_return(JavaThread* java_thread, jvalue value, TosState
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
}
- // retreive or create the state
- JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread);
-
// Check to see if a ForceEarlyReturn was already in progress
if (state->is_earlyret_pending()) {
// Probably possible for JVMTI clients to trigger this, but the
diff --git a/src/share/vm/prims/jvmtiEnvBase.hpp b/src/share/vm/prims/jvmtiEnvBase.hpp
index 477725ffe..e6dd31e58 100644
--- a/src/share/vm/prims/jvmtiEnvBase.hpp
+++ b/src/share/vm/prims/jvmtiEnvBase.hpp
@@ -120,7 +120,7 @@ class JvmtiEnvBase : public CHeapObj {
public:
- bool is_valid() { return _magic == JVMTI_MAGIC; }
+ bool is_valid();
bool is_retransformable() { return _is_retransformable; }
diff --git a/src/share/vm/prims/jvmtiEventController.cpp b/src/share/vm/prims/jvmtiEventController.cpp
index ebadd45e2..4e07d6f84 100644
--- a/src/share/vm/prims/jvmtiEventController.cpp
+++ b/src/share/vm/prims/jvmtiEventController.cpp
@@ -478,6 +478,11 @@ JvmtiEventControllerPrivate::recompute_env_thread_enabled(JvmtiEnvThreadState* e
// set external state accordingly. Only thread-filtered events are included.
jlong
JvmtiEventControllerPrivate::recompute_thread_enabled(JvmtiThreadState *state) {
+ if (state == NULL) {
+ // associated JavaThread is exiting
+ return (jlong)0;
+ }
+
jlong was_any_env_enabled = state->thread_event_enable()->_event_enabled.get_bits();
jlong any_env_enabled = 0;
@@ -553,6 +558,7 @@ JvmtiEventControllerPrivate::recompute_enabled() {
{
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
diff --git a/src/share/vm/prims/jvmtiExport.cpp b/src/share/vm/prims/jvmtiExport.cpp
index a3894b3d6..50ecb4b95 100644
--- a/src/share/vm/prims/jvmtiExport.cpp
+++ b/src/share/vm/prims/jvmtiExport.cpp
@@ -1872,6 +1872,9 @@ void JvmtiExport::post_dynamic_code_generated_while_holding_locks(const char* na
{
// register the stub with the current dynamic code event collector
JvmtiThreadState* state = JvmtiThreadState::state_for(JavaThread::current());
+ // state can only be NULL if the current thread is exiting which
+ // should not happen since we're trying to post an event
+ guarantee(state != NULL, "attempt to register stub via an exiting thread");
JvmtiDynamicCodeEventCollector* collector = state->get_dynamic_code_event_collector();
guarantee(collector != NULL, "attempt to register stub without event collector");
collector->register_stub(name, code_begin, code_end);
@@ -2253,6 +2256,9 @@ void JvmtiExport::cms_ref_processing_epilogue() {
void JvmtiEventCollector::setup_jvmti_thread_state() {
// set this event collector to be the current one.
JvmtiThreadState* state = JvmtiThreadState::state_for(JavaThread::current());
+ // state can only be NULL if the current thread is exiting which
+ // should not happen since we're trying to configure for event collection
+ guarantee(state != NULL, "exiting thread called setup_jvmti_thread_state");
if (is_vm_object_alloc_event()) {
_prev = state->get_vm_object_alloc_event_collector();
state->set_vm_object_alloc_event_collector((JvmtiVMObjectAllocEventCollector *)this);
diff --git a/src/share/vm/prims/jvmtiImpl.cpp b/src/share/vm/prims/jvmtiImpl.cpp
index f9a512c42..5a174b35b 100644
--- a/src/share/vm/prims/jvmtiImpl.cpp
+++ b/src/share/vm/prims/jvmtiImpl.cpp
@@ -238,6 +238,35 @@ JvmtiRawMonitor::~JvmtiRawMonitor() {
}
+bool
+JvmtiRawMonitor::is_valid() {
+ int value = 0;
+
+ // This object might not be a JvmtiRawMonitor so we can't assume
+ // the _magic field is properly aligned. Get the value in a safe
+ // way and then check against JVMTI_RM_MAGIC.
+
+ switch (sizeof(_magic)) {
+ case 2:
+ value = Bytes::get_native_u2((address)&_magic);
+ break;
+
+ case 4:
+ value = Bytes::get_native_u4((address)&_magic);
+ break;
+
+ case 8:
+ value = Bytes::get_native_u8((address)&_magic);
+ break;
+
+ default:
+ guarantee(false, "_magic field is an unexpected size");
+ }
+
+ return value == JVMTI_RM_MAGIC;
+}
+
+
//
// class JvmtiBreakpoint
//
diff --git a/src/share/vm/prims/jvmtiImpl.hpp b/src/share/vm/prims/jvmtiImpl.hpp
index d1b8414e6..2605546c6 100644
--- a/src/share/vm/prims/jvmtiImpl.hpp
+++ b/src/share/vm/prims/jvmtiImpl.hpp
@@ -349,7 +349,7 @@ public:
~JvmtiRawMonitor();
int magic() { return _magic; }
const char *get_name() { return _name; }
- bool is_valid() { return _magic == JVMTI_RM_MAGIC; }
+ bool is_valid();
};
// Onload pending raw monitors
diff --git a/src/share/vm/prims/jvmtiRedefineClasses.cpp b/src/share/vm/prims/jvmtiRedefineClasses.cpp
index ad832c35d..ba9b1d877 100644
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp
@@ -831,6 +831,9 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) {
ResourceMark rm(THREAD);
JvmtiThreadState *state = JvmtiThreadState::state_for(JavaThread::current());
+ // state can only be NULL if the current thread is exiting which
+ // should not happen since we're trying to do a RedefineClasses
+ guarantee(state != NULL, "exiting thread calling load_new_class_versions");
for (int i = 0; i < _class_count; i++) {
oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass);
// classes for primitives cannot be redefined
@@ -1349,39 +1352,39 @@ bool VM_RedefineClasses::rewrite_cp_refs(instanceKlassHandle scratch_class,
// rewrite constant pool references in the methods:
if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) {
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
// rewrite constant pool references in the class_annotations:
if (!rewrite_cp_refs_in_class_annotations(scratch_class, THREAD)) {
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
// rewrite constant pool references in the fields_annotations:
if (!rewrite_cp_refs_in_fields_annotations(scratch_class, THREAD)) {
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
// rewrite constant pool references in the methods_annotations:
if (!rewrite_cp_refs_in_methods_annotations(scratch_class, THREAD)) {
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
// rewrite constant pool references in the methods_parameter_annotations:
if (!rewrite_cp_refs_in_methods_parameter_annotations(scratch_class,
THREAD)) {
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
// rewrite constant pool references in the methods_default_annotations:
if (!rewrite_cp_refs_in_methods_default_annotations(scratch_class,
THREAD)) {
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
@@ -1600,7 +1603,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_annotations_typeArray(
byte_i_ref, THREAD)) {
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
("bad annotation_struct at %d", calc_num_annotations));
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
}
@@ -1666,7 +1669,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_annotation_struct(
byte_i_ref, THREAD)) {
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
("bad element_value at %d", calc_num_element_value_pairs));
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
} // end for each component
@@ -1815,7 +1818,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_element_value(
// field. This is a nested annotation.
if (!rewrite_cp_refs_in_annotation_struct(annotations_typeArray,
byte_i_ref, THREAD)) {
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
break;
@@ -1842,7 +1845,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_element_value(
annotations_typeArray, byte_i_ref, THREAD)) {
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
("bad nested element_value at %d", calc_num_values));
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
}
@@ -1886,7 +1889,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
THREAD)) {
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
("bad field_annotations at %d", i));
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
}
@@ -1923,7 +1926,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
THREAD)) {
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
("bad method_annotations at %d", i));
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
}
@@ -1991,7 +1994,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations(
method_parameter_annotations, byte_i, THREAD)) {
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
("bad method_parameter_annotations at %d", calc_num_parameters));
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
}
@@ -2041,7 +2044,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_default_annotations(
method_default_annotations, byte_i, THREAD)) {
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
("bad default element_value at %d", i));
- // propogate failure back to caller
+ // propagate failure back to caller
return false;
}
}
diff --git a/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp b/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp
index 83192cf16..6762e572b 100644
--- a/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp
+++ b/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp
@@ -49,8 +49,8 @@
// 0x00000400 | 1024 - previous class weak reference mgmt during
// add previous ops (GC)
// 0x00000800 | 2048 - previous class breakpoint mgmt
-// 0x00001000 | 4096 - unused
-// 0x00002000 | 8192 - unused
+// 0x00001000 | 4096 - detect calls to obsolete methods
+// 0x00002000 | 8192 - fail a guarantee() in addition to detection
// 0x00004000 | 16384 - unused
// 0x00008000 | 32768 - old/new method matching/add/delete
// 0x00010000 | 65536 - impl details: CP size info
diff --git a/src/share/vm/prims/jvmtiThreadState.hpp b/src/share/vm/prims/jvmtiThreadState.hpp
index 703d87339..d77d2a8a4 100644
--- a/src/share/vm/prims/jvmtiThreadState.hpp
+++ b/src/share/vm/prims/jvmtiThreadState.hpp
@@ -314,17 +314,24 @@ class JvmtiThreadState : public CHeapObj {
void update_for_pop_top_frame();
// already holding JvmtiThreadState_lock - retrieve or create JvmtiThreadState
+ // Can return NULL if JavaThread is exiting.
inline static JvmtiThreadState *state_for_while_locked(JavaThread *thread) {
assert(JvmtiThreadState_lock->is_locked(), "sanity check");
JvmtiThreadState *state = thread->jvmti_thread_state();
if (state == NULL) {
+ if (thread->is_exiting()) {
+ // don't add a JvmtiThreadState to a thread that is exiting
+ return NULL;
+ }
+
state = new JvmtiThreadState(thread);
}
return state;
}
// retrieve or create JvmtiThreadState
+ // Can return NULL if JavaThread is exiting.
inline static JvmtiThreadState *state_for(JavaThread *thread) {
JvmtiThreadState *state = thread->jvmti_thread_state();
if (state == NULL) {