@@ -3527,7 +3527,15 @@ static void post_thread_start_event(const JavaThread* jt) {
3527
3527
extern const struct JNIInvokeInterface_ jni_InvokeInterface;
3528
3528
3529
3529
// Global invocation API vars
3530
- volatile int vm_created = 0 ;
3530
+ enum VM_Creation_State {
3531
+ NOT_CREATED = 0 ,
3532
+ IN_PROGRESS, // Most JNI operations are permitted during this phase to
3533
+ // allow for initialization actions by libraries and agents.
3534
+ COMPLETE
3535
+ };
3536
+
3537
+ volatile VM_Creation_State vm_created = NOT_CREATED;
3538
+
3531
3539
// Indicate whether it is safe to recreate VM. Recreation is only
3532
3540
// possible after a failed initial creation attempt in some cases.
3533
3541
volatile int safe_to_recreate_vm = 1 ;
@@ -3596,7 +3604,7 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) {
3596
3604
// We use Atomic::xchg rather than Atomic::add/dec since on some platforms
3597
3605
// the add/dec implementations are dependent on whether we are running
3598
3606
// on a multiprocessor Atomic::xchg does not have this problem.
3599
- if (Atomic::xchg (&vm_created, 1 ) == 1 ) {
3607
+ if (Atomic::xchg (&vm_created, IN_PROGRESS) != NOT_CREATED ) {
3600
3608
return JNI_EEXIST; // already created, or create attempt in progress
3601
3609
}
3602
3610
@@ -3609,8 +3617,6 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) {
3609
3617
return JNI_ERR;
3610
3618
}
3611
3619
3612
- assert (vm_created == 1 , " vm_created is true during the creation" );
3613
-
3614
3620
/* *
3615
3621
* Certain errors during initialization are recoverable and do not
3616
3622
* prevent this method from being called again at a later time
@@ -3627,9 +3633,11 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) {
3627
3633
if (result == JNI_OK) {
3628
3634
JavaThread *thread = JavaThread::current ();
3629
3635
assert (!thread->has_pending_exception (), " should have returned not OK" );
3630
- /* thread is thread_in_vm here */
3636
+ // thread is thread_in_vm here
3631
3637
*vm = (JavaVM *)(&main_vm);
3632
3638
*(JNIEnv**)penv = thread->jni_environment ();
3639
+ // mark creation complete for other JNI ops
3640
+ Atomic::release_store (&vm_created, COMPLETE);
3633
3641
3634
3642
#if INCLUDE_JVMCI
3635
3643
if (EnableJVMCI) {
@@ -3694,7 +3702,8 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) {
3694
3702
*(JNIEnv**)penv = 0 ;
3695
3703
// reset vm_created last to avoid race condition. Use OrderAccess to
3696
3704
// control both compiler and architectural-based reordering.
3697
- Atomic::release_store (&vm_created, 0 );
3705
+ assert (vm_created == IN_PROGRESS, " must be" );
3706
+ Atomic::release_store (&vm_created, NOT_CREATED);
3698
3707
}
3699
3708
3700
3709
// Flush stdout and stderr before exit.
@@ -3723,7 +3732,7 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, v
3723
3732
_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs (JavaVM **vm_buf, jsize bufLen, jsize *numVMs) {
3724
3733
HOTSPOT_JNI_GETCREATEDJAVAVMS_ENTRY ((void **) vm_buf, bufLen, (uintptr_t *) numVMs);
3725
3734
3726
- if (vm_created == 1 ) {
3735
+ if (vm_created == COMPLETE ) {
3727
3736
if (numVMs != NULL ) *numVMs = 1 ;
3728
3737
if (bufLen > 0 ) *vm_buf = (JavaVM *)(&main_vm);
3729
3738
} else {
@@ -3743,7 +3752,7 @@ static jint JNICALL jni_DestroyJavaVM_inner(JavaVM *vm) {
3743
3752
jint res = JNI_ERR;
3744
3753
DT_RETURN_MARK (DestroyJavaVM, jint, (const jint&)res);
3745
3754
3746
- if (vm_created == 0 ) {
3755
+ if (vm_created == NOT_CREATED ) {
3747
3756
res = JNI_ERR;
3748
3757
return res;
3749
3758
}
@@ -3767,7 +3776,7 @@ static jint JNICALL jni_DestroyJavaVM_inner(JavaVM *vm) {
3767
3776
ThreadStateTransition::transition_from_native (thread, _thread_in_vm);
3768
3777
Threads::destroy_vm ();
3769
3778
// Don't bother restoring thread state, VM is gone.
3770
- vm_created = 0 ;
3779
+ vm_created = NOT_CREATED ;
3771
3780
return JNI_OK;
3772
3781
}
3773
3782
@@ -3904,7 +3913,8 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae
3904
3913
3905
3914
jint JNICALL jni_AttachCurrentThread (JavaVM *vm, void **penv, void *_args) {
3906
3915
HOTSPOT_JNI_ATTACHCURRENTTHREAD_ENTRY (vm, penv, _args);
3907
- if (vm_created == 0 ) {
3916
+ if (vm_created == NOT_CREATED) {
3917
+ // Not sure how we could possibly get here.
3908
3918
HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN ((uint32_t ) JNI_ERR);
3909
3919
return JNI_ERR;
3910
3920
}
@@ -3917,7 +3927,8 @@ jint JNICALL jni_AttachCurrentThread(JavaVM *vm, void **penv, void *_args) {
3917
3927
3918
3928
jint JNICALL jni_DetachCurrentThread (JavaVM *vm) {
3919
3929
HOTSPOT_JNI_DETACHCURRENTTHREAD_ENTRY (vm);
3920
- if (vm_created == 0 ) {
3930
+ if (vm_created == NOT_CREATED) {
3931
+ // Not sure how we could possibly get here.
3921
3932
HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN (JNI_ERR);
3922
3933
return JNI_ERR;
3923
3934
}
@@ -3980,7 +3991,7 @@ jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) {
3980
3991
jint ret = JNI_ERR;
3981
3992
DT_RETURN_MARK (GetEnv, jint, (const jint&)ret);
3982
3993
3983
- if (vm_created == 0 ) {
3994
+ if (vm_created == NOT_CREATED ) {
3984
3995
*penv = NULL ;
3985
3996
ret = JNI_EDETACHED;
3986
3997
return ret;
@@ -4031,8 +4042,9 @@ jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) {
4031
4042
4032
4043
jint JNICALL jni_AttachCurrentThreadAsDaemon (JavaVM *vm, void **penv, void *_args) {
4033
4044
HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_ENTRY (vm, penv, _args);
4034
- if (vm_created == 0 ) {
4035
- HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN ((uint32_t ) JNI_ERR);
4045
+ if (vm_created == NOT_CREATED) {
4046
+ // Not sure how we could possibly get here.
4047
+ HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN ((uint32_t ) JNI_ERR);
4036
4048
return JNI_ERR;
4037
4049
}
4038
4050
0 commit comments