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

JNI_GetCreatedJavaVMs returns a partially initialized JVM

    XMLWordPrintable

Details

    • b25
    • generic
    • generic

    Description

      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


      Attachments

        Issue Links

          Activity

            People

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

              Dates

                Created:
                Updated:
                Resolved: