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_Sleep
|
||||
JVM_StartThread
|
||||
JVM_StopThread
|
||||
JVM_SupportsCX8
|
||||
JVM_TotalMemory
|
||||
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::_priority_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::_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(_priority_offset, k, vmSymbols::priority_name(), int_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(_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);
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
JavaThread* thr = java_lang_Thread::thread(java_thread);
|
||||
return (thr != NULL);
|
||||
|
@ -379,9 +379,6 @@ class java_lang_Thread : AllStatic {
|
||||
static void set_priority(oop java_thread, ThreadPriority priority);
|
||||
// Thread group
|
||||
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
|
||||
// definition without doing a Java call)
|
||||
static bool is_alive(oop java_thread);
|
||||
@ -434,7 +431,6 @@ class java_lang_Thread_FieldHolder : AllStatic {
|
||||
static int _group_offset;
|
||||
static int _priority_offset;
|
||||
static int _stackSize_offset;
|
||||
static int _stillborn_offset;
|
||||
static int _daemon_offset;
|
||||
static int _thread_status_offset;
|
||||
|
||||
@ -450,9 +446,6 @@ class java_lang_Thread_FieldHolder : AllStatic {
|
||||
|
||||
static jlong stackSize(oop holder);
|
||||
|
||||
static bool is_stillborn(oop holder);
|
||||
static void set_stillborn(oop holder);
|
||||
|
||||
static bool is_daemon(oop holder);
|
||||
static void set_daemon(oop holder);
|
||||
|
||||
|
@ -58,7 +58,6 @@
|
||||
do_klass(System_klass, java_lang_System ) \
|
||||
do_klass(Throwable_klass, java_lang_Throwable ) \
|
||||
do_klass(Error_klass, java_lang_Error ) \
|
||||
do_klass(ThreadDeath_klass, java_lang_ThreadDeath ) \
|
||||
do_klass(Exception_klass, java_lang_Exception ) \
|
||||
do_klass(RuntimeException_klass, java_lang_RuntimeException ) \
|
||||
do_klass(SecurityManager_klass, java_lang_SecurityManager ) \
|
||||
@ -197,4 +196,3 @@
|
||||
/*end*/
|
||||
|
||||
#endif // SHARE_CLASSFILE_VMCLASSMACROS_HPP
|
||||
|
||||
|
@ -70,7 +70,6 @@
|
||||
template(java_lang_Cloneable, "java/lang/Cloneable") \
|
||||
template(java_lang_Throwable, "java/lang/Throwable") \
|
||||
template(java_lang_ClassLoader, "java/lang/ClassLoader") \
|
||||
template(java_lang_ThreadDeath, "java/lang/ThreadDeath") \
|
||||
template(java_lang_Runnable, "java/lang/Runnable") \
|
||||
template(jdk_internal_vm_ContinuationScope, "jdk/internal/vm/ContinuationScope") \
|
||||
template(jdk_internal_vm_StackChunk, "jdk/internal/vm/StackChunk") \
|
||||
@ -394,7 +393,6 @@
|
||||
template(main_name, "main") \
|
||||
template(name_name, "name") \
|
||||
template(priority_name, "priority") \
|
||||
template(stillborn_name, "stillborn") \
|
||||
template(group_name, "group") \
|
||||
template(daemon_name, "daemon") \
|
||||
template(run_method_name, "run") \
|
||||
|
@ -266,9 +266,6 @@ JVM_SetStackWalkContinuation(JNIEnv *env, jobject stackStream, jlong anchor, job
|
||||
JNIEXPORT void JNICALL
|
||||
JVM_StartThread(JNIEnv *env, jobject thread);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JVM_StopThread(JNIEnv *env, jobject thread, jobject exception);
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
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());
|
||||
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)
|
||||
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());
|
||||
JRT_END
|
||||
|
||||
|
@ -1580,14 +1580,10 @@ void JVMCIRuntime::describe_pending_hotspot_exception(JavaThread* THREAD, bool c
|
||||
const char* exception_file = THREAD->exception_file();
|
||||
int exception_line = THREAD->exception_line();
|
||||
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_PENDING_EXCEPTION;
|
||||
}
|
||||
// Clear and ignore any exceptions raised during printing
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
if (!clear) {
|
||||
THREAD->set_pending_exception(exception(), exception_file, exception_line);
|
||||
}
|
||||
|
@ -575,35 +575,31 @@ JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env))
|
||||
if (thread->has_pending_exception()) {
|
||||
Handle ex(thread, thread->pending_exception());
|
||||
thread->clear_pending_exception();
|
||||
if (ex->is_a(vmClasses::ThreadDeath_klass())) {
|
||||
// Don't print anything if we are being killed.
|
||||
jio_fprintf(defaultStream::error_stream(), "Exception ");
|
||||
if (thread != NULL && thread->threadObj() != NULL) {
|
||||
ResourceMark rm(THREAD);
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"in thread \"%s\" ", thread->name());
|
||||
}
|
||||
if (ex->is_a(vmClasses::Throwable_klass())) {
|
||||
JavaValue result(T_VOID);
|
||||
JavaCalls::call_virtual(&result,
|
||||
ex,
|
||||
vmClasses::Throwable_klass(),
|
||||
vmSymbols::printStackTrace_name(),
|
||||
vmSymbols::void_method_signature(),
|
||||
THREAD);
|
||||
// If an exception is thrown in the call it gets thrown away. Not much
|
||||
// we can do with it. The native code that calls this, does not check
|
||||
// for the exception - hence, it might still be in the thread when DestroyVM gets
|
||||
// called, potentially causing a few asserts to trigger - since no pending exception
|
||||
// is expected.
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
} else {
|
||||
jio_fprintf(defaultStream::error_stream(), "Exception ");
|
||||
if (thread != NULL && thread->threadObj() != NULL) {
|
||||
ResourceMark rm(THREAD);
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"in thread \"%s\" ", thread->name());
|
||||
}
|
||||
if (ex->is_a(vmClasses::Throwable_klass())) {
|
||||
JavaValue result(T_VOID);
|
||||
JavaCalls::call_virtual(&result,
|
||||
ex,
|
||||
vmClasses::Throwable_klass(),
|
||||
vmSymbols::printStackTrace_name(),
|
||||
vmSymbols::void_method_signature(),
|
||||
THREAD);
|
||||
// If an exception is thrown in the call it gets thrown away. Not much
|
||||
// we can do with it. The native code that calls this, does not check
|
||||
// for the exception - hence, it might still be in the thread when DestroyVM gets
|
||||
// called, potentially causing a few asserts to trigger - since no pending exception
|
||||
// is expected.
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
} else {
|
||||
ResourceMark rm(THREAD);
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
". Uncaught exception of type %s.",
|
||||
ex->klass()->external_name());
|
||||
}
|
||||
ResourceMark rm(THREAD);
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
". Uncaught exception of type %s.",
|
||||
ex->klass()->external_name());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2926,9 +2926,6 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
|
||||
if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
|
||||
throw_illegal_thread_state = true;
|
||||
} 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 =
|
||||
java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));
|
||||
// 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_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))
|
||||
oop thread_oop = JNIHandles::resolve_non_null(jthread);
|
||||
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();
|
||||
thread->osthread()->set_state(SLEEPING);
|
||||
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.
|
||||
if (!HAS_PENDING_EXCEPTION) {
|
||||
HOTSPOT_THREAD_SLEEP_END(1);
|
||||
|
@ -83,7 +83,6 @@ class HandshakeOperation : public CHeapObj<mtThread> {
|
||||
bool is_async() { return _handshake_cl->is_async(); }
|
||||
bool is_suspend() { return _handshake_cl->is_suspend(); }
|
||||
bool is_async_exception() { return _handshake_cl->is_async_exception(); }
|
||||
bool is_ThreadDeath() { return _handshake_cl->is_ThreadDeath(); }
|
||||
};
|
||||
|
||||
class AsyncHandshakeOperation : public HandshakeOperation {
|
||||
@ -445,9 +444,6 @@ static bool no_async_exception_filter(HandshakeOperation* op) {
|
||||
static bool async_exception_filter(HandshakeOperation* op) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
bool HandshakeState::has_async_exception_operation(bool ThreadDeath_only) {
|
||||
bool HandshakeState::has_async_exception_operation() {
|
||||
if (!has_operation()) return false;
|
||||
MutexLocker ml(_lock.owned_by_self() ? NULL : &_lock, Mutex::_no_safepoint_check_flag);
|
||||
if (!ThreadDeath_only) {
|
||||
return _queue.peek(async_exception_filter) != NULL;
|
||||
} else {
|
||||
return _queue.peek(is_ThreadDeath_filter) != NULL;
|
||||
}
|
||||
return _queue.peek(async_exception_filter) != NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
HandshakeOperation* op;
|
||||
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_suspend() { return false; }
|
||||
virtual bool is_async_exception() { return false; }
|
||||
virtual bool is_ThreadDeath() { return false; }
|
||||
virtual void do_thread(Thread* thread) = 0;
|
||||
};
|
||||
|
||||
@ -132,7 +131,7 @@ class HandshakeState {
|
||||
|
||||
bool has_operation() { return !_queue.is_empty(); }
|
||||
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();
|
||||
|
||||
bool operation_pending(HandshakeOperation* op);
|
||||
|
@ -687,11 +687,9 @@ void JavaThread::thread_main_inner() {
|
||||
assert(JavaThread::current() == this, "sanity check");
|
||||
assert(_threadObj.peek() != NULL, "just checking");
|
||||
|
||||
// Execute thread entry point unless this thread has a pending exception
|
||||
// or has been stopped before starting.
|
||||
// Note: Due to JVM_StopThread we can have pending exceptions already!
|
||||
if (!this->has_pending_exception() &&
|
||||
!java_lang_Thread::is_stillborn(this->threadObj())) {
|
||||
// Execute thread entry point unless this thread has a pending exception.
|
||||
// Note: Due to JVMTI StopThread we can have pending exceptions already!
|
||||
if (!this->has_pending_exception()) {
|
||||
{
|
||||
ResourceMark rm(this);
|
||||
this->set_native_thread_name(this->name());
|
||||
@ -719,15 +717,13 @@ static void ensure_join(JavaThread* thread) {
|
||||
Handle threadObj(thread, thread->threadObj());
|
||||
assert(threadObj.not_null(), "java thread object must exist");
|
||||
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.
|
||||
java_lang_Thread::set_thread_status(threadObj(), JavaThreadStatus::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);
|
||||
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();
|
||||
}
|
||||
|
||||
@ -1067,29 +1063,25 @@ 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
|
||||
set_pending_exception(java_throwable, __FILE__, __LINE__);
|
||||
|
||||
// We cannot call Exceptions::_throw(...) here because we cannot block
|
||||
set_pending_exception(java_throwable, __FILE__, __LINE__);
|
||||
// Clear any extent-local bindings
|
||||
set_extentLocalCache(NULL);
|
||||
oop threadOop = threadObj();
|
||||
assert(threadOop != NULL, "must be");
|
||||
java_lang_Thread::clear_extentLocalBindings(threadOop);
|
||||
|
||||
// Clear any extent-local bindings on ThreadDeath
|
||||
set_extentLocalCache(NULL);
|
||||
oop threadOop = threadObj();
|
||||
assert(threadOop != NULL, "must be");
|
||||
java_lang_Thread::clear_extentLocalBindings(threadOop);
|
||||
|
||||
LogTarget(Info, exceptions) lt;
|
||||
if (lt.is_enabled()) {
|
||||
ResourceMark rm;
|
||||
LogStream ls(lt);
|
||||
ls.print("Async. exception installed at runtime exit (" INTPTR_FORMAT ")", p2i(this));
|
||||
if (has_last_Java_frame()) {
|
||||
frame f = last_frame();
|
||||
ls.print(" (pc: " INTPTR_FORMAT " sp: " INTPTR_FORMAT " )", p2i(f.pc()), p2i(f.sp()));
|
||||
}
|
||||
ls.print_cr(" of type: %s", java_throwable->klass()->external_name());
|
||||
LogTarget(Info, exceptions) lt;
|
||||
if (lt.is_enabled()) {
|
||||
ResourceMark rm;
|
||||
LogStream ls(lt);
|
||||
ls.print("Async. exception installed at runtime exit (" INTPTR_FORMAT ")", p2i(this));
|
||||
if (has_last_Java_frame()) {
|
||||
frame f = last_frame();
|
||||
ls.print(" (pc: " INTPTR_FORMAT " sp: " INTPTR_FORMAT " )", p2i(f.pc()), p2i(f.sp()));
|
||||
}
|
||||
ls.print_cr(" of type: %s", java_throwable->klass()->external_name());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1101,16 +1093,6 @@ void JavaThread::install_async_exception(AsyncExceptionHandshake* aeh) {
|
||||
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();
|
||||
Handshake::execute(aeh, this); // Install asynchronous handshake
|
||||
|
||||
|
@ -222,7 +222,7 @@ class JavaThread: public Thread {
|
||||
void install_async_exception(AsyncExceptionHandshake* aec = NULL);
|
||||
void handle_async_exception(oop java_throwable);
|
||||
public:
|
||||
bool has_async_exception_condition(bool ThreadDeath_only = false);
|
||||
bool has_async_exception_condition();
|
||||
inline void set_pending_unsafe_access_error();
|
||||
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 {
|
||||
OopHandle _exception;
|
||||
bool _is_ThreadDeath;
|
||||
public:
|
||||
AsyncExceptionHandshake(OopHandle& o, const char* name = "AsyncExceptionHandshake")
|
||||
: AsyncHandshakeClosure(name), _exception(o) {
|
||||
_is_ThreadDeath = exception()->is_a(vmClasses::ThreadDeath_klass());
|
||||
}
|
||||
: AsyncHandshakeClosure(name), _exception(o) { }
|
||||
|
||||
~AsyncExceptionHandshake() {
|
||||
Thread* current = Thread::current();
|
||||
@ -108,7 +105,6 @@ class AsyncExceptionHandshake : public AsyncHandshakeClosure {
|
||||
return _exception.resolve();
|
||||
}
|
||||
bool is_async_exception() { return true; }
|
||||
bool is_ThreadDeath() { return _is_ThreadDeath; }
|
||||
};
|
||||
|
||||
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) {
|
||||
return handshake_state()->has_async_exception_operation(ThreadDeath_only);
|
||||
inline bool JavaThread::has_async_exception_condition() {
|
||||
return handshake_state()->has_async_exception_operation();
|
||||
}
|
||||
|
||||
inline JavaThread::NoAsyncExceptionDeliveryMark::NoAsyncExceptionDeliveryMark(JavaThread *t) : _target(t) {
|
||||
|
@ -74,8 +74,7 @@ void ThreadShadow::clear_pending_exception() {
|
||||
|
||||
void ThreadShadow::clear_pending_nonasync_exception() {
|
||||
// Do not clear probable async exceptions.
|
||||
if (!_pending_exception->is_a(vmClasses::ThreadDeath_klass()) &&
|
||||
(_pending_exception->klass() != vmClasses::InternalError_klass() ||
|
||||
if ((_pending_exception->klass() != vmClasses::InternalError_klass() ||
|
||||
java_lang_InternalError::during_unsafe_access(_pending_exception) != JNI_TRUE)) {
|
||||
clear_pending_exception();
|
||||
}
|
||||
@ -427,7 +426,7 @@ void Exceptions::wrap_dynamic_exception(bool is_indy, JavaThread* THREAD) {
|
||||
// in JVMS 6.5.
|
||||
if (exception->is_a(vmClasses::Error_klass())) {
|
||||
// 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) {
|
||||
ls->print_cr("bootstrap method invocation wraps BSME around " PTR_FORMAT, p2i(exception));
|
||||
exception->print_on(ls);
|
||||
|
@ -237,7 +237,7 @@ class Exceptions {
|
||||
#define CHECK_AND_CLEAR_NULL CHECK_AND_CLEAR_(NULL)
|
||||
#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.
|
||||
#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
|
||||
|
@ -247,7 +247,6 @@ public class Thread implements Runnable {
|
||||
volatile int priority;
|
||||
volatile boolean daemon;
|
||||
volatile int threadStatus;
|
||||
boolean stillborn;
|
||||
|
||||
FieldHolder(ThreadGroup group,
|
||||
Runnable task,
|
||||
|
Loading…
Reference in New Issue
Block a user