提交 5a006d61 编写于 作者: D dholmes

6566340: Restore use of stillborn flag to signify a thread that was stopped before it started

Summary: Restore use of stillborn flag
Reviewed-by: acorn, alanb
上级 15178683
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -2651,12 +2651,18 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) ...@@ -2651,12 +2651,18 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
// we operate. // we operate.
MutexLocker mu(Threads_lock); MutexLocker mu(Threads_lock);
// Check to see if we're running a thread that's already exited or was // Since JDK 5 the java.lang.Thread threadStatus is used to prevent
// stopped (is_stillborn) or is still active (thread is not NULL). // re-starting an already started thread, so we should usually find
if (java_lang_Thread::is_stillborn(JNIHandles::resolve_non_null(jthread)) || // that the JavaThread is null. However for a JNI attached thread
java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) { // there is a small window between the Thread object being created
throw_illegal_thread_state = true; // (with its JavaThread set) and the update to its threadStatus, so we
// have to check for this
if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
throw_illegal_thread_state = true;
} else { } else {
// We could also check the stillborn flag to see if this thread was already stopped, but
// for historical reasons we let the thread detect that itself when it starts running
jlong size = jlong size =
java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread)); java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));
// Allocate the C++ Thread structure and create the native thread. The // Allocate the C++ Thread structure and create the native thread. The
...@@ -2704,7 +2710,7 @@ JVM_END ...@@ -2704,7 +2710,7 @@ JVM_END
// JVM_Stop is implemented using a VM_Operation, so threads are forced to safepoints // JVM_Stop is implemented using a VM_Operation, so threads are forced to safepoints
// before the quasi-asynchronous exception is delivered. This is a little obtrusive, // before the quasi-asynchronous exception is delivered. This is a little obtrusive,
// but is thought to be reliable and simple. In the case, where the receiver is the // but is thought to be reliable and simple. In the case, where the receiver is the
// save thread as the sender, no safepoint is needed. // same thread as the sender, no safepoint is needed.
JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable)) JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable))
JVMWrapper("JVM_StopThread"); JVMWrapper("JVM_StopThread");
...@@ -2715,26 +2721,27 @@ JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable)) ...@@ -2715,26 +2721,27 @@ JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable))
oop java_thread = JNIHandles::resolve_non_null(jthread); oop java_thread = JNIHandles::resolve_non_null(jthread);
JavaThread* receiver = java_lang_Thread::thread(java_thread); JavaThread* receiver = java_lang_Thread::thread(java_thread);
Events::log("JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]", receiver, (address)java_thread, throwable); Events::log("JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]", receiver, (address)java_thread, throwable);
// First check if thread already exited // First check if thread is alive
if (receiver != NULL) { if (receiver != NULL) {
// Check if exception is getting thrown at self (use oop equality, since the // Check if exception is getting thrown at self (use oop equality, since the
// target object might exit) // target object might exit)
if (java_thread == thread->threadObj()) { if (java_thread == thread->threadObj()) {
// This is a change from JDK 1.1, but JDK 1.2 will also do it:
// NOTE (from JDK 1.2): this is done solely to prevent stopped
// threads from being restarted.
// Fix for 4314342, 4145910, perhaps others: it now doesn't have
// any effect on the "liveness" of a thread; see
// JVM_IsThreadAlive, below.
if (java_throwable->is_a(SystemDictionary::ThreadDeath_klass())) {
java_lang_Thread::set_stillborn(java_thread);
}
THROW_OOP(java_throwable); THROW_OOP(java_throwable);
} else { } else {
// Enques a VM_Operation to stop all threads and then deliver the exception... // Enques a VM_Operation to stop all threads and then deliver the exception...
Thread::send_async_exception(java_thread, JNIHandles::resolve(throwable)); Thread::send_async_exception(java_thread, JNIHandles::resolve(throwable));
} }
} }
else {
// Either:
// - target thread has not been started before being stopped, or
// - target thread already terminated
// We could read the threadStatus to determine which case it is
// but that is overkill as it doesn't matter. We must set the
// stillborn flag for the first case, and if the thread has already
// exited setting this flag has no affect
java_lang_Thread::set_stillborn(java_thread);
}
JVM_END JVM_END
......
...@@ -1510,11 +1510,11 @@ void JavaThread::thread_main_inner() { ...@@ -1510,11 +1510,11 @@ void JavaThread::thread_main_inner() {
assert(JavaThread::current() == this, "sanity check"); assert(JavaThread::current() == this, "sanity check");
assert(this->threadObj() != NULL, "just checking"); assert(this->threadObj() != NULL, "just checking");
// Execute thread entry point. If this thread is being asked to restart, // Execute thread entry point unless this thread has a pending exception
// or has been stopped before starting, do not reexecute entry point. // or has been stopped before starting.
// Note: Due to JVM_StopThread we can have pending exceptions already! // Note: Due to JVM_StopThread we can have pending exceptions already!
if (!this->has_pending_exception() && !java_lang_Thread::is_stillborn(this->threadObj())) { if (!this->has_pending_exception() &&
// enter the thread's entry point only if we have no pending exceptions !java_lang_Thread::is_stillborn(this->threadObj())) {
HandleMark hm(this); HandleMark hm(this);
this->entry_point()(this, this); this->entry_point()(this, this);
} }
...@@ -1533,13 +1533,10 @@ static void ensure_join(JavaThread* thread) { ...@@ -1533,13 +1533,10 @@ static void ensure_join(JavaThread* thread) {
ObjectLocker lock(threadObj, thread); ObjectLocker lock(threadObj, thread);
// Ignore pending exception (ThreadDeath), since we are exiting anyway // Ignore pending exception (ThreadDeath), since we are exiting anyway
thread->clear_pending_exception(); thread->clear_pending_exception();
// It is of profound importance that we set the stillborn bit and reset the thread object,
// before we do the notify. Since, changing these two variable will make JVM_IsAlive return
// false. So in case another thread is doing a join on this thread , it will detect that the thread
// is dead when it gets notified.
java_lang_Thread::set_stillborn(threadObj());
// Thread is exiting. So set thread_status field in java.lang.Thread class to TERMINATED. // Thread is exiting. So set thread_status field in java.lang.Thread class to TERMINATED.
java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED); java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);
// Clear the native thread instance - this makes isAlive return false and allows the join()
// to complete once we've done the notify_all below
java_lang_Thread::set_thread(threadObj(), NULL); java_lang_Thread::set_thread(threadObj(), NULL);
lock.notify_all(thread); lock.notify_all(thread);
// Ignore pending exception (ThreadDeath), since we are exiting anyway // Ignore pending exception (ThreadDeath), since we are exiting anyway
...@@ -1996,11 +1993,6 @@ void JavaThread::send_thread_stop(oop java_throwable) { ...@@ -1996,11 +1993,6 @@ void JavaThread::send_thread_stop(oop java_throwable) {
// (the compiler thread should not be a Java thread -- fix in 1.4.2) // (the compiler thread should not be a Java thread -- fix in 1.4.2)
if (is_Compiler_thread()) return; if (is_Compiler_thread()) return;
// This is a change from JDK 1.1, but JDK 1.2 will also do it:
if (java_throwable->is_a(SystemDictionary::ThreadDeath_klass())) {
java_lang_Thread::set_stillborn(threadObj());
}
{ {
// Actually throw the Throwable against the target Thread - however // Actually throw the Throwable against the target Thread - however
// only if there is no thread death exception installed already. // only if there is no thread death exception installed already.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册