@@ -3527,7 +3527,14 @@ static void post_thread_start_event(const JavaThread* jt) {
35273527extern const struct JNIInvokeInterface_ jni_InvokeInterface;
35283528
35293529// Global invocation API vars
3530- volatile int vm_created = 0 ;
3530+ enum VM_Creation_State {
3531+ NOT_CREATED = 0 ,
3532+ IN_PROGRESS,
3533+ COMPLETE
3534+ };
3535+
3536+ volatile VM_Creation_State vm_created = NOT_CREATED;
3537+
35313538// Indicate whether it is safe to recreate VM. Recreation is only
35323539// possible after a failed initial creation attempt in some cases.
35333540volatile int safe_to_recreate_vm = 1 ;
@@ -3596,7 +3603,7 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) {
35963603 // We use Atomic::xchg rather than Atomic::add/dec since on some platforms
35973604 // the add/dec implementations are dependent on whether we are running
35983605 // on a multiprocessor Atomic::xchg does not have this problem.
3599- if (Atomic::xchg (&vm_created, 1 ) == 1 ) {
3606+ if (Atomic::xchg (&vm_created, IN_PROGRESS) != NOT_CREATED ) {
36003607 return JNI_EEXIST; // already created, or create attempt in progress
36013608 }
36023609
@@ -3609,8 +3616,6 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) {
36093616 return JNI_ERR;
36103617 }
36113618
3612- assert (vm_created == 1 , " vm_created is true during the creation" );
3613-
36143619 /* *
36153620 * Certain errors during initialization are recoverable and do not
36163621 * prevent this method from being called again at a later time
@@ -3627,9 +3632,11 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) {
36273632 if (result == JNI_OK) {
36283633 JavaThread *thread = JavaThread::current ();
36293634 assert (!thread->has_pending_exception (), " should have returned not OK" );
3630- /* thread is thread_in_vm here */
3635+ // thread is thread_in_vm here
36313636 *vm = (JavaVM *)(&main_vm);
36323637 *(JNIEnv**)penv = thread->jni_environment ();
3638+ // mark creation complete for other JNI ops
3639+ Atomic::release_store (&vm_created, COMPLETE);
36333640
36343641#if INCLUDE_JVMCI
36353642 if (EnableJVMCI) {
@@ -3694,7 +3701,8 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) {
36943701 *(JNIEnv**)penv = 0 ;
36953702 // reset vm_created last to avoid race condition. Use OrderAccess to
36963703 // control both compiler and architectural-based reordering.
3697- Atomic::release_store (&vm_created, 0 );
3704+ assert (vm_created == IN_PROGRESS, " must be" );
3705+ Atomic::release_store (&vm_created, NOT_CREATED);
36983706 }
36993707
37003708 // Flush stdout and stderr before exit.
@@ -3723,7 +3731,7 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, v
37233731_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs (JavaVM **vm_buf, jsize bufLen, jsize *numVMs) {
37243732 HOTSPOT_JNI_GETCREATEDJAVAVMS_ENTRY ((void **) vm_buf, bufLen, (uintptr_t *) numVMs);
37253733
3726- if (vm_created == 1 ) {
3734+ if (vm_created == COMPLETE ) {
37273735 if (numVMs != NULL ) *numVMs = 1 ;
37283736 if (bufLen > 0 ) *vm_buf = (JavaVM *)(&main_vm);
37293737 } else {
@@ -3743,7 +3751,7 @@ static jint JNICALL jni_DestroyJavaVM_inner(JavaVM *vm) {
37433751 jint res = JNI_ERR;
37443752 DT_RETURN_MARK (DestroyJavaVM, jint, (const jint&)res);
37453753
3746- if (vm_created == 0 ) {
3754+ if (vm_created != COMPLETE ) {
37473755 res = JNI_ERR;
37483756 return res;
37493757 }
@@ -3767,7 +3775,7 @@ static jint JNICALL jni_DestroyJavaVM_inner(JavaVM *vm) {
37673775 ThreadStateTransition::transition_from_native (thread, _thread_in_vm);
37683776 Threads::destroy_vm ();
37693777 // Don't bother restoring thread state, VM is gone.
3770- vm_created = 0 ;
3778+ vm_created = NOT_CREATED ;
37713779 return JNI_OK;
37723780}
37733781
@@ -3904,7 +3912,8 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae
39043912
39053913jint JNICALL jni_AttachCurrentThread (JavaVM *vm, void **penv, void *_args) {
39063914 HOTSPOT_JNI_ATTACHCURRENTTHREAD_ENTRY (vm, penv, _args);
3907- if (vm_created == 0 ) {
3915+ if (vm_created != COMPLETE) {
3916+ // Not sure how we could possibly get here.
39083917 HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN ((uint32_t ) JNI_ERR);
39093918 return JNI_ERR;
39103919 }
@@ -3917,7 +3926,8 @@ jint JNICALL jni_AttachCurrentThread(JavaVM *vm, void **penv, void *_args) {
39173926
39183927jint JNICALL jni_DetachCurrentThread (JavaVM *vm) {
39193928 HOTSPOT_JNI_DETACHCURRENTTHREAD_ENTRY (vm);
3920- if (vm_created == 0 ) {
3929+ if (vm_created != COMPLETE) {
3930+ // Not sure how we could possibly get here.
39213931 HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN (JNI_ERR);
39223932 return JNI_ERR;
39233933 }
@@ -3980,7 +3990,10 @@ jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) {
39803990 jint ret = JNI_ERR;
39813991 DT_RETURN_MARK (GetEnv, jint, (const jint&)ret);
39823992
3983- if (vm_created == 0 ) {
3993+ // We can be called by native libraries in the JDK during VM
3994+ // initialization, so only bail-out if something seems very wrong.
3995+ // Though how would we get here in that case?
3996+ if (vm_created == NOT_CREATED) {
39843997 *penv = NULL ;
39853998 ret = JNI_EDETACHED;
39863999 return ret;
@@ -4031,7 +4044,8 @@ jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) {
40314044
40324045jint JNICALL jni_AttachCurrentThreadAsDaemon (JavaVM *vm, void **penv, void *_args) {
40334046 HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_ENTRY (vm, penv, _args);
4034- if (vm_created == 0 ) {
4047+ if (vm_created != COMPLETE) {
4048+ // Not sure how we could possibly get here.
40354049 HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN ((uint32_t ) JNI_ERR);
40364050 return JNI_ERR;
40374051 }
0 commit comments