JDK 11 | JDK 17 | JDK 21 |
---|---|---|
11.0.28-oracleFixed | 17.0.15-oracleFixed | 21 b25Fixed |
CSR :
|
|
Causes :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
JDK-8309249 :
|
ADDITIONAL SYSTEM INFORMATION : OS: Ubuntu 22.04.2 LTS OpenJDK compiled with debugslow from https://github.com/openjdk/jdk/ and commit 8d49ba9e8d3095f850b3007b56488a0c0cf8ddff openjdk version "21-internal" 2023-09-19 OpenJDK Runtime Environment (slowdebug build 21-internal-adhoc.fpoli.jdk) OpenJDK 64-Bit Server VM (slowdebug build 21-internal-adhoc.fpoli.jdk, mixed mode, sharing) A DESCRIPTION OF THE PROBLEM : `JNI_GetCreatedJavaVMs` returns a pointer to a VM that has not been fully initialized. Thus, trying to `AttachCurrentThread` on the returned VM causes an internal assertion to fail. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Run `make run`. The program will crash with high probability (100% on my computer so far). ACTUAL - The call to `JNI_GetCreatedJavaVMs` returns a pointer to a VM that has not been fully initialized. In fact, by calling `AttachCurrentThread` on the returned VM the following debug assertion fails: ``` # # A fatal error has been detected by the Java Runtime Environment: # # Internal Error (/home/fpoli/src/jdk/src/hotspot/share/runtime/mutex.cpp:275), pid=2128085, tid=2128087 # assert(os::mutex_init_done()) failed: Too early! # # JRE version: (21.0) (slowdebug build ) # Java VM: OpenJDK 64-Bit Server VM (slowdebug 21-internal-adhoc.fpoli.jdk, mixed mode, sharing, tiered, compressed class ptrs, unknown gc, linux-amd64) # Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /home/fpoli/src/jni-bug/core.2128085) # # An error report file with more information is saved as: # /home/fpoli/src/jni-bug/hs_err_pid2128085.log ``` ---------- BEGIN SOURCE ---------- C++ code: ``` #include <jni.h> #include <string.h> #include <pthread.h> #include <iostream> using namespace std; #define NUM_THREADS 2 void *thread_runner(void *threadid) { long tid; tid = (long)threadid; JavaVM *vm; JNIEnv *env; JavaVMInitArgs vm_args; JavaVMOption* options = new JavaVMOption[0]; vm_args.version = JNI_VERSION_1_6; vm_args.nOptions = 0; vm_args.options = options; vm_args.ignoreUnrecognized = false; cout << "[" << tid << "] BEGIN JNI_CreateJavaVM" << endl; jint create_res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args); cout << "[" << tid << "] END JNI_CreateJavaVM" << endl; if (create_res != JNI_OK) { cout << "[" << tid << "] Error creating JVM: " << create_res << endl; if (create_res == -5) { jsize count; cout << "[" << tid << "] BEGIN JNI_CreateJavaVM" << endl; jint get_res = JNI_GetCreatedJavaVMs(&vm, 1, &count); cout << "[" << tid << "] END JNI_CreateJavaVM" << endl; if (get_res != JNI_OK) { cout << "[" << tid << "] Error obtaining created JVMs: " << get_res << endl; pthread_exit(NULL); } else { cout << "[" << tid << "] Obtained an existing JVM" << endl; } cout << "[" << tid << "] BEGIN AttachCurrentThread" << endl; vm->AttachCurrentThread((void **)&env, NULL); cout << "[" << tid << "] END AttachCurrentThread" << endl; } else { pthread_exit(NULL); } } else { cout << "[" << tid << "] Created a JVM" << endl; } delete options; pthread_exit(NULL); } int main () { pthread_t threads[NUM_THREADS]; for (int i = 0; i < NUM_THREADS; i++ ) { cout << "[*] Creating thread " << i << endl; int status = pthread_create(&threads[i], NULL, thread_runner, (void *)i); if (status) { cout << "[*] Error creating thread: " << status << endl; exit(-1); } } for (int i = 0; i < NUM_THREADS; i++ ) { pthread_join(threads[i], NULL); cout << "[*] Joined thread " << i << endl; } return 0; } ``` Makefile: ``` main: $(CXX) \ -Wall -Wextra -g \ -L${JAVA_HOME}/lib/server/ \ -I${JAVA_HOME}/include/ \ -I${JAVA_HOME}/include/linux/ \ main.cpp \ -ljvm run: main LD_LIBRARY_PATH="${JAVA_HOME}/lib/server/:${LD_LIBRARY_PATH}" ./a.out ``` ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : Unknown FREQUENCY : often
|