8293592: Remove JVM_StopThread, stillborn, and related cleanup
Reviewed-by: alanb, sspitsyn, rehn, coleenp
This commit is contained in:
parent
739fdec7ea
commit
763d4bf074
@ -204,7 +204,6 @@ JVM_SetStackWalkContinuation
|
|||||||
JVM_SetThreadPriority
|
JVM_SetThreadPriority
|
||||||
JVM_Sleep
|
JVM_Sleep
|
||||||
JVM_StartThread
|
JVM_StartThread
|
||||||
JVM_StopThread
|
|
||||||
JVM_SupportsCX8
|
JVM_SupportsCX8
|
||||||
JVM_TotalMemory
|
JVM_TotalMemory
|
||||||
JVM_UnloadLibrary
|
JVM_UnloadLibrary
|
||||||
|
@ -1642,7 +1642,6 @@ void java_lang_Class::set_classRedefinedCount(oop the_class_mirror, int value) {
|
|||||||
int java_lang_Thread_FieldHolder::_group_offset;
|
int java_lang_Thread_FieldHolder::_group_offset;
|
||||||
int java_lang_Thread_FieldHolder::_priority_offset;
|
int java_lang_Thread_FieldHolder::_priority_offset;
|
||||||
int java_lang_Thread_FieldHolder::_stackSize_offset;
|
int java_lang_Thread_FieldHolder::_stackSize_offset;
|
||||||
int java_lang_Thread_FieldHolder::_stillborn_offset;
|
|
||||||
int java_lang_Thread_FieldHolder::_daemon_offset;
|
int java_lang_Thread_FieldHolder::_daemon_offset;
|
||||||
int java_lang_Thread_FieldHolder::_thread_status_offset;
|
int java_lang_Thread_FieldHolder::_thread_status_offset;
|
||||||
|
|
||||||
@ -1650,7 +1649,6 @@ int java_lang_Thread_FieldHolder::_thread_status_offset;
|
|||||||
macro(_group_offset, k, vmSymbols::group_name(), threadgroup_signature, false); \
|
macro(_group_offset, k, vmSymbols::group_name(), threadgroup_signature, false); \
|
||||||
macro(_priority_offset, k, vmSymbols::priority_name(), int_signature, false); \
|
macro(_priority_offset, k, vmSymbols::priority_name(), int_signature, false); \
|
||||||
macro(_stackSize_offset, k, "stackSize", long_signature, false); \
|
macro(_stackSize_offset, k, "stackSize", long_signature, false); \
|
||||||
macro(_stillborn_offset, k, "stillborn", bool_signature, false); \
|
|
||||||
macro(_daemon_offset, k, vmSymbols::daemon_name(), bool_signature, false); \
|
macro(_daemon_offset, k, vmSymbols::daemon_name(), bool_signature, false); \
|
||||||
macro(_thread_status_offset, k, "threadStatus", int_signature, false)
|
macro(_thread_status_offset, k, "threadStatus", int_signature, false)
|
||||||
|
|
||||||
@ -1683,14 +1681,6 @@ jlong java_lang_Thread_FieldHolder::stackSize(oop holder) {
|
|||||||
return holder->long_field(_stackSize_offset);
|
return holder->long_field(_stackSize_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool java_lang_Thread_FieldHolder::is_stillborn(oop holder) {
|
|
||||||
return holder->bool_field(_stillborn_offset) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void java_lang_Thread_FieldHolder::set_stillborn(oop holder) {
|
|
||||||
holder->bool_field_put(_stillborn_offset, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool java_lang_Thread_FieldHolder::is_daemon(oop holder) {
|
bool java_lang_Thread_FieldHolder::is_daemon(oop holder) {
|
||||||
return holder->bool_field(_daemon_offset) != 0;
|
return holder->bool_field(_daemon_offset) != 0;
|
||||||
}
|
}
|
||||||
@ -1854,21 +1844,6 @@ oop java_lang_Thread::threadGroup(oop java_thread) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool java_lang_Thread::is_stillborn(oop java_thread) {
|
|
||||||
oop holder = java_lang_Thread::holder(java_thread);
|
|
||||||
assert(holder != NULL, "Java Thread not initialized");
|
|
||||||
return java_lang_Thread_FieldHolder::is_stillborn(holder);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// We never have reason to turn the stillborn bit off
|
|
||||||
void java_lang_Thread::set_stillborn(oop java_thread) {
|
|
||||||
oop holder = java_lang_Thread::holder(java_thread);
|
|
||||||
assert(holder != NULL, "Java Thread not initialized");
|
|
||||||
java_lang_Thread_FieldHolder::set_stillborn(holder);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool java_lang_Thread::is_alive(oop java_thread) {
|
bool java_lang_Thread::is_alive(oop java_thread) {
|
||||||
JavaThread* thr = java_lang_Thread::thread(java_thread);
|
JavaThread* thr = java_lang_Thread::thread(java_thread);
|
||||||
return (thr != NULL);
|
return (thr != NULL);
|
||||||
|
@ -379,9 +379,6 @@ class java_lang_Thread : AllStatic {
|
|||||||
static void set_priority(oop java_thread, ThreadPriority priority);
|
static void set_priority(oop java_thread, ThreadPriority priority);
|
||||||
// Thread group
|
// Thread group
|
||||||
static oop threadGroup(oop java_thread);
|
static oop threadGroup(oop java_thread);
|
||||||
// Stillborn
|
|
||||||
static bool is_stillborn(oop java_thread);
|
|
||||||
static void set_stillborn(oop java_thread);
|
|
||||||
// Alive (NOTE: this is not really a field, but provides the correct
|
// Alive (NOTE: this is not really a field, but provides the correct
|
||||||
// definition without doing a Java call)
|
// definition without doing a Java call)
|
||||||
static bool is_alive(oop java_thread);
|
static bool is_alive(oop java_thread);
|
||||||
@ -434,7 +431,6 @@ class java_lang_Thread_FieldHolder : AllStatic {
|
|||||||
static int _group_offset;
|
static int _group_offset;
|
||||||
static int _priority_offset;
|
static int _priority_offset;
|
||||||
static int _stackSize_offset;
|
static int _stackSize_offset;
|
||||||
static int _stillborn_offset;
|
|
||||||
static int _daemon_offset;
|
static int _daemon_offset;
|
||||||
static int _thread_status_offset;
|
static int _thread_status_offset;
|
||||||
|
|
||||||
@ -450,9 +446,6 @@ class java_lang_Thread_FieldHolder : AllStatic {
|
|||||||
|
|
||||||
static jlong stackSize(oop holder);
|
static jlong stackSize(oop holder);
|
||||||
|
|
||||||
static bool is_stillborn(oop holder);
|
|
||||||
static void set_stillborn(oop holder);
|
|
||||||
|
|
||||||
static bool is_daemon(oop holder);
|
static bool is_daemon(oop holder);
|
||||||
static void set_daemon(oop holder);
|
static void set_daemon(oop holder);
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@
|
|||||||
do_klass(System_klass, java_lang_System ) \
|
do_klass(System_klass, java_lang_System ) \
|
||||||
do_klass(Throwable_klass, java_lang_Throwable ) \
|
do_klass(Throwable_klass, java_lang_Throwable ) \
|
||||||
do_klass(Error_klass, java_lang_Error ) \
|
do_klass(Error_klass, java_lang_Error ) \
|
||||||
do_klass(ThreadDeath_klass, java_lang_ThreadDeath ) \
|
|
||||||
do_klass(Exception_klass, java_lang_Exception ) \
|
do_klass(Exception_klass, java_lang_Exception ) \
|
||||||
do_klass(RuntimeException_klass, java_lang_RuntimeException ) \
|
do_klass(RuntimeException_klass, java_lang_RuntimeException ) \
|
||||||
do_klass(SecurityManager_klass, java_lang_SecurityManager ) \
|
do_klass(SecurityManager_klass, java_lang_SecurityManager ) \
|
||||||
@ -197,4 +196,3 @@
|
|||||||
/*end*/
|
/*end*/
|
||||||
|
|
||||||
#endif // SHARE_CLASSFILE_VMCLASSMACROS_HPP
|
#endif // SHARE_CLASSFILE_VMCLASSMACROS_HPP
|
||||||
|
|
||||||
|
@ -70,7 +70,6 @@
|
|||||||
template(java_lang_Cloneable, "java/lang/Cloneable") \
|
template(java_lang_Cloneable, "java/lang/Cloneable") \
|
||||||
template(java_lang_Throwable, "java/lang/Throwable") \
|
template(java_lang_Throwable, "java/lang/Throwable") \
|
||||||
template(java_lang_ClassLoader, "java/lang/ClassLoader") \
|
template(java_lang_ClassLoader, "java/lang/ClassLoader") \
|
||||||
template(java_lang_ThreadDeath, "java/lang/ThreadDeath") \
|
|
||||||
template(java_lang_Runnable, "java/lang/Runnable") \
|
template(java_lang_Runnable, "java/lang/Runnable") \
|
||||||
template(jdk_internal_vm_ContinuationScope, "jdk/internal/vm/ContinuationScope") \
|
template(jdk_internal_vm_ContinuationScope, "jdk/internal/vm/ContinuationScope") \
|
||||||
template(jdk_internal_vm_StackChunk, "jdk/internal/vm/StackChunk") \
|
template(jdk_internal_vm_StackChunk, "jdk/internal/vm/StackChunk") \
|
||||||
@ -394,7 +393,6 @@
|
|||||||
template(main_name, "main") \
|
template(main_name, "main") \
|
||||||
template(name_name, "name") \
|
template(name_name, "name") \
|
||||||
template(priority_name, "priority") \
|
template(priority_name, "priority") \
|
||||||
template(stillborn_name, "stillborn") \
|
|
||||||
template(group_name, "group") \
|
template(group_name, "group") \
|
||||||
template(daemon_name, "daemon") \
|
template(daemon_name, "daemon") \
|
||||||
template(run_method_name, "run") \
|
template(run_method_name, "run") \
|
||||||
|
@ -266,9 +266,6 @@ JVM_SetStackWalkContinuation(JNIEnv *env, jobject stackStream, jlong anchor, job
|
|||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
JVM_StartThread(JNIEnv *env, jobject thread);
|
JVM_StartThread(JNIEnv *env, jobject thread);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
|
||||||
JVM_StopThread(JNIEnv *env, jobject thread, jobject exception);
|
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
JVM_IsThreadAlive(JNIEnv *env, jobject thread);
|
JVM_IsThreadAlive(JNIEnv *env, jobject thread);
|
||||||
|
|
||||||
|
@ -776,11 +776,7 @@ JRT_ENTRY(void, InterpreterRuntime::new_illegal_monitor_state_exception(JavaThre
|
|||||||
Handle exception(current, current->vm_result());
|
Handle exception(current, current->vm_result());
|
||||||
assert(exception() != NULL, "vm result should be set");
|
assert(exception() != NULL, "vm result should be set");
|
||||||
current->set_vm_result(NULL); // clear vm result before continuing (may cause memory leaks and assert failures)
|
current->set_vm_result(NULL); // clear vm result before continuing (may cause memory leaks and assert failures)
|
||||||
if (!exception->is_a(vmClasses::ThreadDeath_klass())) {
|
exception = get_preinitialized_exception(vmClasses::IllegalMonitorStateException_klass(), CATCH);
|
||||||
exception = get_preinitialized_exception(
|
|
||||||
vmClasses::IllegalMonitorStateException_klass(),
|
|
||||||
CATCH);
|
|
||||||
}
|
|
||||||
current->set_vm_result(exception());
|
current->set_vm_result(exception());
|
||||||
JRT_END
|
JRT_END
|
||||||
|
|
||||||
|
@ -1580,14 +1580,10 @@ void JVMCIRuntime::describe_pending_hotspot_exception(JavaThread* THREAD, bool c
|
|||||||
const char* exception_file = THREAD->exception_file();
|
const char* exception_file = THREAD->exception_file();
|
||||||
int exception_line = THREAD->exception_line();
|
int exception_line = THREAD->exception_line();
|
||||||
CLEAR_PENDING_EXCEPTION;
|
CLEAR_PENDING_EXCEPTION;
|
||||||
if (exception->is_a(vmClasses::ThreadDeath_klass())) {
|
|
||||||
// Don't print anything if we are being killed.
|
|
||||||
} else {
|
|
||||||
java_lang_Throwable::print_stack_trace(exception, tty);
|
java_lang_Throwable::print_stack_trace(exception, tty);
|
||||||
|
|
||||||
// Clear and ignore any exceptions raised during printing
|
// Clear and ignore any exceptions raised during printing
|
||||||
CLEAR_PENDING_EXCEPTION;
|
CLEAR_PENDING_EXCEPTION;
|
||||||
}
|
|
||||||
if (!clear) {
|
if (!clear) {
|
||||||
THREAD->set_pending_exception(exception(), exception_file, exception_line);
|
THREAD->set_pending_exception(exception(), exception_file, exception_line);
|
||||||
}
|
}
|
||||||
|
@ -575,9 +575,6 @@ JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env))
|
|||||||
if (thread->has_pending_exception()) {
|
if (thread->has_pending_exception()) {
|
||||||
Handle ex(thread, thread->pending_exception());
|
Handle ex(thread, thread->pending_exception());
|
||||||
thread->clear_pending_exception();
|
thread->clear_pending_exception();
|
||||||
if (ex->is_a(vmClasses::ThreadDeath_klass())) {
|
|
||||||
// Don't print anything if we are being killed.
|
|
||||||
} else {
|
|
||||||
jio_fprintf(defaultStream::error_stream(), "Exception ");
|
jio_fprintf(defaultStream::error_stream(), "Exception ");
|
||||||
if (thread != NULL && thread->threadObj() != NULL) {
|
if (thread != NULL && thread->threadObj() != NULL) {
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
@ -605,7 +602,6 @@ JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env))
|
|||||||
ex->klass()->external_name());
|
ex->klass()->external_name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
HOTSPOT_JNI_EXCEPTIONDESCRIBE_RETURN();
|
HOTSPOT_JNI_EXCEPTIONDESCRIBE_RETURN();
|
||||||
JNI_END
|
JNI_END
|
||||||
|
@ -2926,9 +2926,6 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
|
|||||||
if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
|
if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
|
||||||
throw_illegal_thread_state = true;
|
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
|
||||||
@ -2981,45 +2978,6 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
|
|||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
// 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,
|
|
||||||
// but is thought to be reliable and simple. In the case, where the receiver is the
|
|
||||||
// same thread as the sender, no VM_Operation is needed.
|
|
||||||
JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable))
|
|
||||||
ThreadsListHandle tlh(thread);
|
|
||||||
oop java_throwable = JNIHandles::resolve(throwable);
|
|
||||||
if (java_throwable == NULL) {
|
|
||||||
THROW(vmSymbols::java_lang_NullPointerException());
|
|
||||||
}
|
|
||||||
oop java_thread = NULL;
|
|
||||||
JavaThread* receiver = NULL;
|
|
||||||
bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, &java_thread);
|
|
||||||
Events::log_exception(thread,
|
|
||||||
"JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]",
|
|
||||||
p2i(receiver), p2i(java_thread), p2i(throwable));
|
|
||||||
|
|
||||||
if (is_alive) {
|
|
||||||
// jthread refers to a live JavaThread.
|
|
||||||
if (thread == receiver) {
|
|
||||||
// Exception is getting thrown at self so no VM_Operation needed.
|
|
||||||
THROW_OOP(java_throwable);
|
|
||||||
} else {
|
|
||||||
// Use a VM_Operation to throw the exception.
|
|
||||||
JavaThread::send_async_exception(receiver, java_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 effect.
|
|
||||||
java_lang_Thread::set_stillborn(java_thread);
|
|
||||||
}
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
JVM_ENTRY(jboolean, JVM_IsThreadAlive(JNIEnv* env, jobject jthread))
|
JVM_ENTRY(jboolean, JVM_IsThreadAlive(JNIEnv* env, jobject jthread))
|
||||||
oop thread_oop = JNIHandles::resolve_non_null(jthread);
|
oop thread_oop = JNIHandles::resolve_non_null(jthread);
|
||||||
return java_lang_Thread::is_alive(thread_oop);
|
return java_lang_Thread::is_alive(thread_oop);
|
||||||
@ -3070,7 +3028,7 @@ JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))
|
|||||||
ThreadState old_state = thread->osthread()->get_state();
|
ThreadState old_state = thread->osthread()->get_state();
|
||||||
thread->osthread()->set_state(SLEEPING);
|
thread->osthread()->set_state(SLEEPING);
|
||||||
if (!thread->sleep(millis)) { // interrupted
|
if (!thread->sleep(millis)) { // interrupted
|
||||||
// An asynchronous exception (e.g., ThreadDeathException) could have been thrown on
|
// An asynchronous exception could have been thrown on
|
||||||
// us while we were sleeping. We do not overwrite those.
|
// us while we were sleeping. We do not overwrite those.
|
||||||
if (!HAS_PENDING_EXCEPTION) {
|
if (!HAS_PENDING_EXCEPTION) {
|
||||||
HOTSPOT_THREAD_SLEEP_END(1);
|
HOTSPOT_THREAD_SLEEP_END(1);
|
||||||
|
@ -83,7 +83,6 @@ class HandshakeOperation : public CHeapObj<mtThread> {
|
|||||||
bool is_async() { return _handshake_cl->is_async(); }
|
bool is_async() { return _handshake_cl->is_async(); }
|
||||||
bool is_suspend() { return _handshake_cl->is_suspend(); }
|
bool is_suspend() { return _handshake_cl->is_suspend(); }
|
||||||
bool is_async_exception() { return _handshake_cl->is_async_exception(); }
|
bool is_async_exception() { return _handshake_cl->is_async_exception(); }
|
||||||
bool is_ThreadDeath() { return _handshake_cl->is_ThreadDeath(); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AsyncHandshakeOperation : public HandshakeOperation {
|
class AsyncHandshakeOperation : public HandshakeOperation {
|
||||||
@ -445,9 +444,6 @@ static bool no_async_exception_filter(HandshakeOperation* op) {
|
|||||||
static bool async_exception_filter(HandshakeOperation* op) {
|
static bool async_exception_filter(HandshakeOperation* op) {
|
||||||
return op->is_async_exception();
|
return op->is_async_exception();
|
||||||
}
|
}
|
||||||
static bool is_ThreadDeath_filter(HandshakeOperation* op) {
|
|
||||||
return op->is_ThreadDeath();
|
|
||||||
}
|
|
||||||
static bool no_suspend_no_async_exception_filter(HandshakeOperation* op) {
|
static bool no_suspend_no_async_exception_filter(HandshakeOperation* op) {
|
||||||
return !op->is_suspend() && !op->is_async_exception();
|
return !op->is_suspend() && !op->is_async_exception();
|
||||||
}
|
}
|
||||||
@ -503,18 +499,14 @@ bool HandshakeState::has_operation(bool allow_suspend, bool check_async_exceptio
|
|||||||
return get_op_for_self(allow_suspend, check_async_exception) != NULL;
|
return get_op_for_self(allow_suspend, check_async_exception) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HandshakeState::has_async_exception_operation(bool ThreadDeath_only) {
|
bool HandshakeState::has_async_exception_operation() {
|
||||||
if (!has_operation()) return false;
|
if (!has_operation()) return false;
|
||||||
MutexLocker ml(_lock.owned_by_self() ? NULL : &_lock, Mutex::_no_safepoint_check_flag);
|
MutexLocker ml(_lock.owned_by_self() ? NULL : &_lock, Mutex::_no_safepoint_check_flag);
|
||||||
if (!ThreadDeath_only) {
|
|
||||||
return _queue.peek(async_exception_filter) != NULL;
|
return _queue.peek(async_exception_filter) != NULL;
|
||||||
} else {
|
|
||||||
return _queue.peek(is_ThreadDeath_filter) != NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandshakeState::clean_async_exception_operation() {
|
void HandshakeState::clean_async_exception_operation() {
|
||||||
while (has_async_exception_operation(/* ThreadDeath_only */ false)) {
|
while (has_async_exception_operation()) {
|
||||||
MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
|
MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
|
||||||
HandshakeOperation* op;
|
HandshakeOperation* op;
|
||||||
op = _queue.peek(async_exception_filter);
|
op = _queue.peek(async_exception_filter);
|
||||||
|
@ -54,7 +54,6 @@ class HandshakeClosure : public ThreadClosure, public CHeapObj<mtThread> {
|
|||||||
virtual bool is_async() { return false; }
|
virtual bool is_async() { return false; }
|
||||||
virtual bool is_suspend() { return false; }
|
virtual bool is_suspend() { return false; }
|
||||||
virtual bool is_async_exception() { return false; }
|
virtual bool is_async_exception() { return false; }
|
||||||
virtual bool is_ThreadDeath() { return false; }
|
|
||||||
virtual void do_thread(Thread* thread) = 0;
|
virtual void do_thread(Thread* thread) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -132,7 +131,7 @@ class HandshakeState {
|
|||||||
|
|
||||||
bool has_operation() { return !_queue.is_empty(); }
|
bool has_operation() { return !_queue.is_empty(); }
|
||||||
bool has_operation(bool allow_suspend, bool check_async_exception);
|
bool has_operation(bool allow_suspend, bool check_async_exception);
|
||||||
bool has_async_exception_operation(bool ThreadDeath_only);
|
bool has_async_exception_operation();
|
||||||
void clean_async_exception_operation();
|
void clean_async_exception_operation();
|
||||||
|
|
||||||
bool operation_pending(HandshakeOperation* op);
|
bool operation_pending(HandshakeOperation* op);
|
||||||
|
@ -687,11 +687,9 @@ void JavaThread::thread_main_inner() {
|
|||||||
assert(JavaThread::current() == this, "sanity check");
|
assert(JavaThread::current() == this, "sanity check");
|
||||||
assert(_threadObj.peek() != NULL, "just checking");
|
assert(_threadObj.peek() != NULL, "just checking");
|
||||||
|
|
||||||
// Execute thread entry point unless this thread has a pending exception
|
// Execute thread entry point unless this thread has a pending exception.
|
||||||
// or has been stopped before starting.
|
// Note: Due to JVMTI StopThread we can have pending exceptions already!
|
||||||
// Note: Due to JVM_StopThread we can have pending exceptions already!
|
if (!this->has_pending_exception()) {
|
||||||
if (!this->has_pending_exception() &&
|
|
||||||
!java_lang_Thread::is_stillborn(this->threadObj())) {
|
|
||||||
{
|
{
|
||||||
ResourceMark rm(this);
|
ResourceMark rm(this);
|
||||||
this->set_native_thread_name(this->name());
|
this->set_native_thread_name(this->name());
|
||||||
@ -719,15 +717,13 @@ static void ensure_join(JavaThread* thread) {
|
|||||||
Handle threadObj(thread, thread->threadObj());
|
Handle threadObj(thread, thread->threadObj());
|
||||||
assert(threadObj.not_null(), "java thread object must exist");
|
assert(threadObj.not_null(), "java thread object must exist");
|
||||||
ObjectLocker lock(threadObj, thread);
|
ObjectLocker lock(threadObj, thread);
|
||||||
// Ignore pending exception (ThreadDeath), since we are exiting anyway
|
|
||||||
thread->clear_pending_exception();
|
|
||||||
// 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(), JavaThreadStatus::TERMINATED);
|
java_lang_Thread::set_thread_status(threadObj(), JavaThreadStatus::TERMINATED);
|
||||||
// Clear the native thread instance - this makes isAlive return false and allows the join()
|
// Clear the native thread instance - this makes isAlive return false and allows the join()
|
||||||
// to complete once we've done the notify_all below
|
// 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, since we are exiting anyway
|
||||||
thread->clear_pending_exception();
|
thread->clear_pending_exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1067,13 +1063,10 @@ void JavaThread::handle_async_exception(oop java_throwable) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only overwrite an already pending exception if it is not a ThreadDeath.
|
|
||||||
if (!has_pending_exception() || !pending_exception()->is_a(vmClasses::ThreadDeath_klass())) {
|
|
||||||
|
|
||||||
// We cannot call Exceptions::_throw(...) here because we cannot block
|
// We cannot call Exceptions::_throw(...) here because we cannot block
|
||||||
set_pending_exception(java_throwable, __FILE__, __LINE__);
|
set_pending_exception(java_throwable, __FILE__, __LINE__);
|
||||||
|
|
||||||
// Clear any extent-local bindings on ThreadDeath
|
// Clear any extent-local bindings
|
||||||
set_extentLocalCache(NULL);
|
set_extentLocalCache(NULL);
|
||||||
oop threadOop = threadObj();
|
oop threadOop = threadObj();
|
||||||
assert(threadOop != NULL, "must be");
|
assert(threadOop != NULL, "must be");
|
||||||
@ -1090,7 +1083,6 @@ void JavaThread::handle_async_exception(oop java_throwable) {
|
|||||||
}
|
}
|
||||||
ls.print_cr(" of type: %s", java_throwable->klass()->external_name());
|
ls.print_cr(" of type: %s", java_throwable->klass()->external_name());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaThread::install_async_exception(AsyncExceptionHandshake* aeh) {
|
void JavaThread::install_async_exception(AsyncExceptionHandshake* aeh) {
|
||||||
@ -1101,16 +1093,6 @@ void JavaThread::install_async_exception(AsyncExceptionHandshake* aeh) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't install a new pending async exception if there is already
|
|
||||||
// a pending ThreadDeath one. Just interrupt thread from potential
|
|
||||||
// wait()/sleep()/park() and return.
|
|
||||||
if (has_async_exception_condition(true /* ThreadDeath_only */)) {
|
|
||||||
java_lang_Thread::set_interrupted(threadObj(), true);
|
|
||||||
this->interrupt();
|
|
||||||
delete aeh;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
oop exception = aeh->exception();
|
oop exception = aeh->exception();
|
||||||
Handshake::execute(aeh, this); // Install asynchronous handshake
|
Handshake::execute(aeh, this); // Install asynchronous handshake
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ class JavaThread: public Thread {
|
|||||||
void install_async_exception(AsyncExceptionHandshake* aec = NULL);
|
void install_async_exception(AsyncExceptionHandshake* aec = NULL);
|
||||||
void handle_async_exception(oop java_throwable);
|
void handle_async_exception(oop java_throwable);
|
||||||
public:
|
public:
|
||||||
bool has_async_exception_condition(bool ThreadDeath_only = false);
|
bool has_async_exception_condition();
|
||||||
inline void set_pending_unsafe_access_error();
|
inline void set_pending_unsafe_access_error();
|
||||||
static void send_async_exception(JavaThread* jt, oop java_throwable);
|
static void send_async_exception(JavaThread* jt, oop java_throwable);
|
||||||
|
|
||||||
|
@ -79,12 +79,9 @@ inline void JavaThread::clear_carrier_thread_suspended() {
|
|||||||
|
|
||||||
class AsyncExceptionHandshake : public AsyncHandshakeClosure {
|
class AsyncExceptionHandshake : public AsyncHandshakeClosure {
|
||||||
OopHandle _exception;
|
OopHandle _exception;
|
||||||
bool _is_ThreadDeath;
|
|
||||||
public:
|
public:
|
||||||
AsyncExceptionHandshake(OopHandle& o, const char* name = "AsyncExceptionHandshake")
|
AsyncExceptionHandshake(OopHandle& o, const char* name = "AsyncExceptionHandshake")
|
||||||
: AsyncHandshakeClosure(name), _exception(o) {
|
: AsyncHandshakeClosure(name), _exception(o) { }
|
||||||
_is_ThreadDeath = exception()->is_a(vmClasses::ThreadDeath_klass());
|
|
||||||
}
|
|
||||||
|
|
||||||
~AsyncExceptionHandshake() {
|
~AsyncExceptionHandshake() {
|
||||||
Thread* current = Thread::current();
|
Thread* current = Thread::current();
|
||||||
@ -108,7 +105,6 @@ class AsyncExceptionHandshake : public AsyncHandshakeClosure {
|
|||||||
return _exception.resolve();
|
return _exception.resolve();
|
||||||
}
|
}
|
||||||
bool is_async_exception() { return true; }
|
bool is_async_exception() { return true; }
|
||||||
bool is_ThreadDeath() { return _is_ThreadDeath; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class UnsafeAccessErrorHandshake : public AsyncHandshakeClosure {
|
class UnsafeAccessErrorHandshake : public AsyncHandshakeClosure {
|
||||||
@ -129,8 +125,8 @@ inline void JavaThread::set_pending_unsafe_access_error() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool JavaThread::has_async_exception_condition(bool ThreadDeath_only) {
|
inline bool JavaThread::has_async_exception_condition() {
|
||||||
return handshake_state()->has_async_exception_operation(ThreadDeath_only);
|
return handshake_state()->has_async_exception_operation();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JavaThread::NoAsyncExceptionDeliveryMark::NoAsyncExceptionDeliveryMark(JavaThread *t) : _target(t) {
|
inline JavaThread::NoAsyncExceptionDeliveryMark::NoAsyncExceptionDeliveryMark(JavaThread *t) : _target(t) {
|
||||||
|
@ -74,8 +74,7 @@ void ThreadShadow::clear_pending_exception() {
|
|||||||
|
|
||||||
void ThreadShadow::clear_pending_nonasync_exception() {
|
void ThreadShadow::clear_pending_nonasync_exception() {
|
||||||
// Do not clear probable async exceptions.
|
// Do not clear probable async exceptions.
|
||||||
if (!_pending_exception->is_a(vmClasses::ThreadDeath_klass()) &&
|
if ((_pending_exception->klass() != vmClasses::InternalError_klass() ||
|
||||||
(_pending_exception->klass() != vmClasses::InternalError_klass() ||
|
|
||||||
java_lang_InternalError::during_unsafe_access(_pending_exception) != JNI_TRUE)) {
|
java_lang_InternalError::during_unsafe_access(_pending_exception) != JNI_TRUE)) {
|
||||||
clear_pending_exception();
|
clear_pending_exception();
|
||||||
}
|
}
|
||||||
@ -427,7 +426,7 @@ void Exceptions::wrap_dynamic_exception(bool is_indy, JavaThread* THREAD) {
|
|||||||
// in JVMS 6.5.
|
// in JVMS 6.5.
|
||||||
if (exception->is_a(vmClasses::Error_klass())) {
|
if (exception->is_a(vmClasses::Error_klass())) {
|
||||||
// Pass through an Error, including BootstrapMethodError, any other form
|
// Pass through an Error, including BootstrapMethodError, any other form
|
||||||
// of linkage error, or say ThreadDeath/OutOfMemoryError
|
// of linkage error, or say OutOfMemoryError
|
||||||
if (ls != NULL) {
|
if (ls != NULL) {
|
||||||
ls->print_cr("bootstrap method invocation wraps BSME around " PTR_FORMAT, p2i(exception));
|
ls->print_cr("bootstrap method invocation wraps BSME around " PTR_FORMAT, p2i(exception));
|
||||||
exception->print_on(ls);
|
exception->print_on(ls);
|
||||||
|
@ -237,7 +237,7 @@ class Exceptions {
|
|||||||
#define CHECK_AND_CLEAR_NULL CHECK_AND_CLEAR_(NULL)
|
#define CHECK_AND_CLEAR_NULL CHECK_AND_CLEAR_(NULL)
|
||||||
#define CHECK_AND_CLEAR_false CHECK_AND_CLEAR_(false)
|
#define CHECK_AND_CLEAR_false CHECK_AND_CLEAR_(false)
|
||||||
|
|
||||||
// CAUTION: These macros clears all exceptions except probable async exceptions j.l.InternalError and j.l.ThreadDeath.
|
// CAUTION: These macros clears all exceptions except probable async exceptions j.l.InternalError.
|
||||||
// So use it with caution.
|
// So use it with caution.
|
||||||
#define CLEAR_PENDING_NONASYNC_EXCEPTION (((ThreadShadow*)THREAD)->clear_pending_nonasync_exception())
|
#define CLEAR_PENDING_NONASYNC_EXCEPTION (((ThreadShadow*)THREAD)->clear_pending_nonasync_exception())
|
||||||
#define CHECK_AND_CLEAR_NONASYNC THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_NONASYNC_EXCEPTION; return; } (void)(0
|
#define CHECK_AND_CLEAR_NONASYNC THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_NONASYNC_EXCEPTION; return; } (void)(0
|
||||||
|
@ -247,7 +247,6 @@ public class Thread implements Runnable {
|
|||||||
volatile int priority;
|
volatile int priority;
|
||||||
volatile boolean daemon;
|
volatile boolean daemon;
|
||||||
volatile int threadStatus;
|
volatile int threadStatus;
|
||||||
boolean stillborn;
|
|
||||||
|
|
||||||
FieldHolder(ThreadGroup group,
|
FieldHolder(ThreadGroup group,
|
||||||
Runnable task,
|
Runnable task,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user