@@ -1365,6 +1365,7 @@ static bool is_daemon(oop threadObj) {
13651365// cleanup_failed_attach_current_thread as well.
13661366void JavaThread::exit (bool destroy_vm, ExitType exit_type) {
13671367 assert (this == JavaThread::current (), " thread consistency check" );
1368+ assert (!is_exiting (), " should not be exiting or terminated already" );
13681369
13691370 elapsedTimer _timer_exit_phase1;
13701371 elapsedTimer _timer_exit_phase2;
@@ -1426,18 +1427,23 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
14261427 if (JvmtiExport::should_post_thread_life ()) {
14271428 JvmtiExport::post_thread_end (this );
14281429 }
1429-
1430- // The careful dance between thread suspension and exit is handled here.
1431- // Since we are in thread_in_vm state and suspension is done with handshakes,
1432- // we can just put in the exiting state and it will be correctly handled.
1433- set_terminated (_thread_exiting);
1434-
1435- ThreadService::current_thread_exiting (this , is_daemon (threadObj ()));
14361430 } else {
1437- assert (!is_terminated () && !is_exiting (), " must not be exiting" );
14381431 // before_exit() has already posted JVMTI THREAD_END events
14391432 }
14401433
1434+ // Cleanup any pending async exception now since we cannot access oops after
1435+ // BarrierSet::barrier_set()->on_thread_detach() has been executed.
1436+ if (has_async_exception_condition ()) {
1437+ handshake_state ()->clean_async_exception_operation ();
1438+ }
1439+
1440+ // The careful dance between thread suspension and exit is handled here.
1441+ // Since we are in thread_in_vm state and suspension is done with handshakes,
1442+ // we can just put in the exiting state and it will be correctly handled.
1443+ // Also, no more async exceptions will be added to the queue after this point.
1444+ set_terminated (_thread_exiting);
1445+ ThreadService::current_thread_exiting (this , is_daemon (threadObj ()));
1446+
14411447 if (log_is_enabled (Debug, os, thread, timer)) {
14421448 _timer_exit_phase1.stop ();
14431449 _timer_exit_phase2.start ();
@@ -1529,7 +1535,8 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
15291535 }
15301536#endif // INCLUDE_JVMCI
15311537
1532- // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread
1538+ // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread.
1539+ // We call BarrierSet::barrier_set()->on_thread_detach() here so no touching of oops after this point.
15331540 Threads::remove (this , daemon);
15341541
15351542 if (log_is_enabled (Debug, os, thread, timer)) {
@@ -1699,8 +1706,9 @@ void JavaThread::handle_async_exception(oop java_throwable) {
16991706}
17001707
17011708void JavaThread::install_async_exception (AsyncExceptionHandshake* aeh) {
1702- // Do not throw asynchronous exceptions against the compiler thread.
1703- if (!can_call_java ()) {
1709+ // Do not throw asynchronous exceptions against the compiler thread
1710+ // or if the thread is already exiting.
1711+ if (!can_call_java () || is_exiting ()) {
17041712 delete aeh;
17051713 return ;
17061714 }
0 commit comments