6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
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
This commit is contained in:
parent
74a99e1e82
commit
56fe18e375
@ -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) {
|
|||||||
|
|
||||||
// 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) {
|
|||||||
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) {
|
|||||||
// 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) {
|
|||||||
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) {
|
|||||||
|
|
||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
// 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() {
|
|||||||
{
|
{
|
||||||
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
|
|||||||
{
|
{
|
||||||
// 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() {
|
|||||||
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) {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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:
|
|||||||
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; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user