提交 2543ed9a 编写于 作者: D dcubed

6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness

Summary: Check for NULL return values from jvmti_thread_state() and state_for() and return a JVM TI error code as appropriate.
Reviewed-by: coleenp, swamyv
上级 5ed51852
...@@ -99,6 +99,9 @@ JvmtiEnv::SetThreadLocalStorage(JavaThread* java_thread, const void* data) { ...@@ -99,6 +99,9 @@ JvmtiEnv::SetThreadLocalStorage(JavaThread* java_thread, const void* data) {
} }
// otherwise, create the state // otherwise, create the state
state = JvmtiThreadState::state_for(java_thread); 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); state->env_thread_state(this)->set_agent_thread_local_storage_data((void*)data);
return JVMTI_ERROR_NONE; return JVMTI_ERROR_NONE;
...@@ -1308,6 +1311,9 @@ JvmtiEnv::GetFrameCount(JavaThread* java_thread, jint* count_ptr) { ...@@ -1308,6 +1311,9 @@ JvmtiEnv::GetFrameCount(JavaThread* java_thread, jint* count_ptr) {
// retrieve or create JvmtiThreadState. // retrieve or create JvmtiThreadState.
JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread); JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread);
if (state == NULL) {
return JVMTI_ERROR_THREAD_NOT_ALIVE;
}
uint32_t debug_bits = 0; uint32_t debug_bits = 0;
if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { if (is_thread_fully_suspended(java_thread, true, &debug_bits)) {
err = get_frame_count(state, count_ptr); err = get_frame_count(state, count_ptr);
...@@ -1329,6 +1335,12 @@ JvmtiEnv::PopFrame(JavaThread* java_thread) { ...@@ -1329,6 +1335,12 @@ JvmtiEnv::PopFrame(JavaThread* java_thread) {
HandleMark hm(current_thread); HandleMark hm(current_thread);
uint32_t debug_bits = 0; 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 // Check if java_thread is fully suspended
if (!is_thread_fully_suspended(java_thread, true /* wait for suspend completion */, &debug_bits)) { if (!is_thread_fully_suspended(java_thread, true /* wait for suspend completion */, &debug_bits)) {
return JVMTI_ERROR_THREAD_NOT_SUSPENDED; return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
...@@ -1399,9 +1411,6 @@ JvmtiEnv::PopFrame(JavaThread* java_thread) { ...@@ -1399,9 +1411,6 @@ JvmtiEnv::PopFrame(JavaThread* java_thread) {
// It's fine to update the thread state here because no JVMTI events // It's fine to update the thread state here because no JVMTI events
// shall be posted for this PopFrame. // shall be posted for this PopFrame.
// retreive or create the state
JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread);
state->update_for_pop_top_frame(); state->update_for_pop_top_frame();
java_thread->set_popframe_condition(JavaThread::popframe_pending_bit); java_thread->set_popframe_condition(JavaThread::popframe_pending_bit);
// Set pending step flag for this popframe and it is cleared when next // Set pending step flag for this popframe and it is cleared when next
...@@ -1445,6 +1454,11 @@ JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) { ...@@ -1445,6 +1454,11 @@ JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) {
ResourceMark rm; ResourceMark rm;
uint32_t debug_bits = 0; 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)) { if (!JvmtiEnv::is_thread_fully_suspended(java_thread, true, &debug_bits)) {
return JVMTI_ERROR_THREAD_NOT_SUSPENDED; return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
} }
...@@ -1464,7 +1478,6 @@ JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) { ...@@ -1464,7 +1478,6 @@ JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) {
assert(vf->frame_pointer() != NULL, "frame pointer mustn't be NULL"); 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; int frame_number = state->count_frames() - depth;
state->env_thread_state(this)->set_frame_pop(frame_number); state->env_thread_state(this)->set_frame_pop(frame_number);
......
...@@ -1322,6 +1322,12 @@ JvmtiEnvBase::force_early_return(JavaThread* java_thread, jvalue value, TosState ...@@ -1322,6 +1322,12 @@ JvmtiEnvBase::force_early_return(JavaThread* java_thread, jvalue value, TosState
HandleMark hm(current_thread); HandleMark hm(current_thread);
uint32_t debug_bits = 0; 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 // Check if java_thread is fully suspended
if (!is_thread_fully_suspended(java_thread, if (!is_thread_fully_suspended(java_thread,
true /* wait for suspend completion */, true /* wait for suspend completion */,
...@@ -1329,9 +1335,6 @@ JvmtiEnvBase::force_early_return(JavaThread* java_thread, jvalue value, TosState ...@@ -1329,9 +1335,6 @@ JvmtiEnvBase::force_early_return(JavaThread* java_thread, jvalue value, TosState
return JVMTI_ERROR_THREAD_NOT_SUSPENDED; 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 // Check to see if a ForceEarlyReturn was already in progress
if (state->is_earlyret_pending()) { if (state->is_earlyret_pending()) {
// Probably possible for JVMTI clients to trigger this, but the // Probably possible for JVMTI clients to trigger this, but the
......
...@@ -478,6 +478,11 @@ JvmtiEventControllerPrivate::recompute_env_thread_enabled(JvmtiEnvThreadState* e ...@@ -478,6 +478,11 @@ JvmtiEventControllerPrivate::recompute_env_thread_enabled(JvmtiEnvThreadState* e
// set external state accordingly. Only thread-filtered events are included. // set external state accordingly. Only thread-filtered events are included.
jlong jlong
JvmtiEventControllerPrivate::recompute_thread_enabled(JvmtiThreadState *state) { 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 was_any_env_enabled = state->thread_event_enable()->_event_enabled.get_bits();
jlong any_env_enabled = 0; jlong any_env_enabled = 0;
...@@ -553,6 +558,7 @@ JvmtiEventControllerPrivate::recompute_enabled() { ...@@ -553,6 +558,7 @@ JvmtiEventControllerPrivate::recompute_enabled() {
{ {
MutexLocker mu(Threads_lock); //hold the Threads_lock for the iteration MutexLocker mu(Threads_lock); //hold the Threads_lock for the iteration
for (JavaThread *tp = Threads::first(); tp != NULL; tp = tp->next()) { 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 JvmtiThreadState::state_for_while_locked(tp); // create the thread state if missing
} }
}// release Threads_lock }// release Threads_lock
......
...@@ -1872,6 +1872,9 @@ void JvmtiExport::post_dynamic_code_generated_while_holding_locks(const char* na ...@@ -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 // register the stub with the current dynamic code event collector
JvmtiThreadState* state = JvmtiThreadState::state_for(JavaThread::current()); 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(); JvmtiDynamicCodeEventCollector* collector = state->get_dynamic_code_event_collector();
guarantee(collector != NULL, "attempt to register stub without event collector"); guarantee(collector != NULL, "attempt to register stub without event collector");
collector->register_stub(name, code_begin, code_end); collector->register_stub(name, code_begin, code_end);
...@@ -2253,6 +2256,9 @@ void JvmtiExport::cms_ref_processing_epilogue() { ...@@ -2253,6 +2256,9 @@ void JvmtiExport::cms_ref_processing_epilogue() {
void JvmtiEventCollector::setup_jvmti_thread_state() { void JvmtiEventCollector::setup_jvmti_thread_state() {
// set this event collector to be the current one. // set this event collector to be the current one.
JvmtiThreadState* state = JvmtiThreadState::state_for(JavaThread::current()); 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()) { if (is_vm_object_alloc_event()) {
_prev = state->get_vm_object_alloc_event_collector(); _prev = state->get_vm_object_alloc_event_collector();
state->set_vm_object_alloc_event_collector((JvmtiVMObjectAllocEventCollector *)this); state->set_vm_object_alloc_event_collector((JvmtiVMObjectAllocEventCollector *)this);
......
...@@ -831,6 +831,9 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { ...@@ -831,6 +831,9 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) {
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
JvmtiThreadState *state = JvmtiThreadState::state_for(JavaThread::current()); 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++) { for (int i = 0; i < _class_count; i++) {
oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass); oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass);
// classes for primitives cannot be redefined // classes for primitives cannot be redefined
......
...@@ -314,6 +314,7 @@ class JvmtiThreadState : public CHeapObj { ...@@ -314,6 +314,7 @@ class JvmtiThreadState : public CHeapObj {
void update_for_pop_top_frame(); void update_for_pop_top_frame();
// already holding JvmtiThreadState_lock - retrieve or create JvmtiThreadState // already holding JvmtiThreadState_lock - retrieve or create JvmtiThreadState
// Can return NULL if JavaThread is exiting.
inline static JvmtiThreadState *state_for_while_locked(JavaThread *thread) { inline static JvmtiThreadState *state_for_while_locked(JavaThread *thread) {
assert(JvmtiThreadState_lock->is_locked(), "sanity check"); assert(JvmtiThreadState_lock->is_locked(), "sanity check");
...@@ -330,6 +331,7 @@ class JvmtiThreadState : public CHeapObj { ...@@ -330,6 +331,7 @@ class JvmtiThreadState : public CHeapObj {
} }
// retrieve or create JvmtiThreadState // retrieve or create JvmtiThreadState
// Can return NULL if JavaThread is exiting.
inline static JvmtiThreadState *state_for(JavaThread *thread) { inline static JvmtiThreadState *state_for(JavaThread *thread) {
JvmtiThreadState *state = thread->jvmti_thread_state(); JvmtiThreadState *state = thread->jvmti_thread_state();
if (state == NULL) { if (state == NULL) {
......
...@@ -1345,6 +1345,13 @@ public: ...@@ -1345,6 +1345,13 @@ public:
public: public:
// Thread local information maintained by JVMTI. // Thread local information maintained by JVMTI.
void set_jvmti_thread_state(JvmtiThreadState *value) { _jvmti_thread_state = value; } void set_jvmti_thread_state(JvmtiThreadState *value) { _jvmti_thread_state = value; }
// A JvmtiThreadState is lazily allocated. This jvmti_thread_state()
// getter is used to get this JavaThread's JvmtiThreadState if it has
// one which means NULL can be returned. JvmtiThreadState::state_for()
// is used to get the specified JavaThread's JvmtiThreadState if it has
// one or it allocates a new JvmtiThreadState for the JavaThread and
// returns it. JvmtiThreadState::state_for() will return NULL only if
// the specified JavaThread is exiting.
JvmtiThreadState *jvmti_thread_state() const { return _jvmti_thread_state; } JvmtiThreadState *jvmti_thread_state() const { return _jvmti_thread_state; }
static ByteSize jvmti_thread_state_offset() { return byte_offset_of(JavaThread, _jvmti_thread_state); } static ByteSize jvmti_thread_state_offset() { return byte_offset_of(JavaThread, _jvmti_thread_state); }
void set_jvmti_get_loaded_classes_closure(JvmtiGetLoadedClassesClosure* value) { _jvmti_get_loaded_classes_closure = value; } void set_jvmti_get_loaded_classes_closure(JvmtiGetLoadedClassesClosure* value) { _jvmti_get_loaded_classes_closure = value; }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册