-
Bug
-
Resolution: Fixed
-
P3
-
21
-
b25
-
generic
-
generic
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8342969 | 17.0.15-oracle | Daniel Skantz | P3 | Resolved | Fixed | b01 |
JDK-8345455 | 17.0.15 | Goetz Lindenmaier | P3 | Resolved | Fixed | b01 |
JDK-8346091 | 17.0.14.0.1-oracle | Daniel Skantz | P3 | Resolved | Fixed | b01 |
JDK-8343820 | 17.0.13.0.1-oracle | Daniel Skantz | P3 | Closed | Fixed | b01 |
JDK-8347932 | 11.0.28-oracle | Daniel Skantz | P3 | Resolved | Fixed | master |
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
- backported by
-
JDK-8342969 JNI_GetCreatedJavaVMs returns a partially initialized JVM
-
- Resolved
-
-
JDK-8345455 JNI_GetCreatedJavaVMs returns a partially initialized JVM
-
- Resolved
-
-
JDK-8346091 JNI_GetCreatedJavaVMs returns a partially initialized JVM
-
- Resolved
-
-
JDK-8347932 JNI_GetCreatedJavaVMs returns a partially initialized JVM
-
- Resolved
-
-
JDK-8343820 JNI_GetCreatedJavaVMs returns a partially initialized JVM
-
- Closed
-
- csr for
-
JDK-8308816 JNI_GetCreatedJavaVMs returns a partially initialized JVM
-
- Closed
-
- relates to
-
JDK-8309171 Test vmTestbase/nsk/jvmti/scenarios/jni_interception/JI05/ji05t001/TestDescription.java fails after JDK-8308341
-
- Closed
-
-
JDK-8309243 Re-examine when JNI methods should be allowed during the VM initialization process
-
- Open
-
-
JDK-8330470 TLAB initialization may cause div by zero
-
- Open
-
- links to
-
Commit openjdk/jdk/1e6770fb
-
Commit(master) openjdk/jdk17u-dev/ed63b718
-
Review openjdk/jdk/14139
-
Review(master) openjdk/jdk17u-dev/3084