@@ -1365,6 +1365,7 @@ static bool is_daemon(oop threadObj) {
1365
1365
// cleanup_failed_attach_current_thread as well.
1366
1366
void JavaThread::exit (bool destroy_vm, ExitType exit_type) {
1367
1367
assert (this == JavaThread::current (), " thread consistency check" );
1368
+ assert (!is_exiting (), " should not be exiting or terminated already" );
1368
1369
1369
1370
elapsedTimer _timer_exit_phase1;
1370
1371
elapsedTimer _timer_exit_phase2;
@@ -1426,18 +1427,23 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
1426
1427
if (JvmtiExport::should_post_thread_life ()) {
1427
1428
JvmtiExport::post_thread_end (this );
1428
1429
}
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 ()));
1436
1430
} else {
1437
- assert (!is_terminated () && !is_exiting (), " must not be exiting" );
1438
1431
// before_exit() has already posted JVMTI THREAD_END events
1439
1432
}
1440
1433
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
+
1441
1447
if (log_is_enabled (Debug, os, thread, timer)) {
1442
1448
_timer_exit_phase1.stop ();
1443
1449
_timer_exit_phase2.start ();
@@ -1529,7 +1535,8 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
1529
1535
}
1530
1536
#endif // INCLUDE_JVMCI
1531
1537
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.
1533
1540
Threads::remove (this , daemon );
1534
1541
1535
1542
if (log_is_enabled (Debug, os, thread, timer)) {
@@ -1699,8 +1706,9 @@ void JavaThread::handle_async_exception(oop java_throwable) {
1699
1706
}
1700
1707
1701
1708
void 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 ()) {
1704
1712
delete aeh;
1705
1713
return ;
1706
1714
}
0 commit comments