Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8308341

JNI_GetCreatedJavaVMs returns a partially initialized JVM

XMLWordPrintable

    • b25
    • generic
    • generic

        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


              dholmes David Holmes
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              11 Start watching this issue

                Created:
                Updated:
                Resolved: