--- old/src/hotspot/share/prims/jni.cpp 2019-04-01 22:22:38.628488183 +0000 +++ new/src/hotspot/share/prims/jni.cpp 2019-04-01 22:22:37.928471738 +0000 @@ -4166,7 +4166,7 @@ if (attach_failed) { // Added missing cleanup - thread->cleanup_failed_attach_current_thread(); + thread->cleanup_failed_attach_current_thread(daemon); return JNI_ERR; } --- old/src/hotspot/share/runtime/thread.cpp 2019-04-01 22:22:40.728537517 +0000 +++ new/src/hotspot/share/runtime/thread.cpp 2019-04-01 22:22:40.032521166 +0000 @@ -2023,6 +2023,10 @@ _timer_exit_phase1.stop(); _timer_exit_phase2.start(); } + + // Capture daemon status before the thread is marked as terminated. + bool daemon = is_daemon(threadObj()); + // Notify waiters on thread object. This has to be done after exit() is called // on the thread (if the thread is the last thread in a daemon ThreadGroup the // group should have the destroyed bit set before waiters are notified). @@ -2091,7 +2095,7 @@ _timer_exit_phase4.start(); } // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread - Threads::remove(this); + Threads::remove(this, daemon); if (log_is_enabled(Debug, os, thread, timer)) { _timer_exit_phase4.stop(); @@ -2109,7 +2113,7 @@ } } -void JavaThread::cleanup_failed_attach_current_thread() { +void JavaThread::cleanup_failed_attach_current_thread(bool is_daemon) { if (active_handles() != NULL) { JNIHandleBlock* block = active_handles(); set_active_handles(NULL); @@ -2131,7 +2135,7 @@ BarrierSet::barrier_set()->on_thread_detach(this); - Threads::remove(this); + Threads::remove(this, is_daemon); this->smr_delete(); } @@ -4457,7 +4461,7 @@ Events::log(p, "Thread added: " INTPTR_FORMAT, p2i(p)); } -void Threads::remove(JavaThread* p) { +void Threads::remove(JavaThread* p, bool is_daemon) { // Reclaim the ObjectMonitors from the omInUseList and omFreeList of the moribund thread. ObjectSynchronizer::omFlush(p); @@ -4486,11 +4490,8 @@ } _number_of_threads--; - oop threadObj = p->threadObj(); - bool daemon = true; - if (!is_daemon(threadObj)) { + if (!is_daemon) { _number_of_non_daemon_threads--; - daemon = false; // Only one thread left, do a notify on the Threads_lock so a thread waiting // on destroy_vm will wake up. @@ -4498,7 +4499,7 @@ Threads_lock->notify_all(); } } - ThreadService::remove_thread(p, daemon); + ThreadService::remove_thread(p, is_daemon); // Make sure that safepoint code disregard this thread. This is needed since // the thread might mess around with locks after this point. This can cause it --- old/src/hotspot/share/runtime/thread.hpp 2019-04-01 22:22:42.712584126 +0000 +++ new/src/hotspot/share/runtime/thread.hpp 2019-04-01 22:22:42.016567775 +0000 @@ -1243,7 +1243,7 @@ }; void exit(bool destroy_vm, ExitType exit_type = normal_exit); - void cleanup_failed_attach_current_thread(); + void cleanup_failed_attach_current_thread(bool is_daemon); // Testers virtual bool is_Java_thread() const { return true; } @@ -2236,7 +2236,7 @@ // force_daemon is a concession to JNI, where we may need to add a // thread to the thread list before allocating its thread object static void add(JavaThread* p, bool force_daemon = false); - static void remove(JavaThread* p); + static void remove(JavaThread* p, bool is_daemon); static void non_java_threads_do(ThreadClosure* tc); static void java_threads_do(ThreadClosure* tc); static void java_threads_and_vm_thread_do(ThreadClosure* tc); --- old/test/hotspot/gtest/threadHelper.inline.hpp 2019-04-01 22:22:44.328622089 +0000 +++ new/test/hotspot/gtest/threadHelper.inline.hpp 2019-04-01 22:22:43.636605833 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,7 @@ // Override as JavaThread::post_run() calls JavaThread::exit which // expects a valid thread object oop. virtual void post_run() { - Threads::remove(this); + Threads::remove(this, false); this->smr_delete(); } @@ -118,7 +118,7 @@ // Override as JavaThread::post_run() calls JavaThread::exit which // expects a valid thread object oop. And we need to call signal. void post_run() { - Threads::remove(this); + Threads::remove(this, false); _post->signal(); this->smr_delete(); }