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

JNI_CreateJavaVM function hangs/freezes process on Java versions above 16

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      Window 10 64bit, tested all JDK's from version 8, up until version 19. Tested with Oracle JDKs, Adoptium, Liberica, Zulu and Coretto. Issue is present in all of them.

      A DESCRIPTION OF THE PROBLEM :
      I'm dynamically loading a dll in a c/c++ application which is using JNI to to start a JVM and load a jar. I created a small app (c/c++) to test this. From this application, it loads up fine with no issues, however when running the exact same code from inside an Unreal Engine game code (c++), the whole process freezes when the JNI_CreateJavaVM function is called. I tested all java versions from java 8 to nightly builds of java19 and found out that up until java 16.0.2, it works without
       any issues. But all versions after Java16 freeze the game process completely when calling that function.

      I have no error messages or crash logs, so I'm assuming the process is freezed. Because the game freezes. If there's any other debugging methods I can use to provide you with more information, please let me know.

      REGRESSION : Last worked in version 16

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      As I said, I cant reproduce the issue on the simple app I created to test it, I can only reproduce it from inside the code base of my unreal engine game but I'm sure this issue is not specific to unreal engine since java16 and below dont have this problem.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Result should be the same as with Java16, process should not freeze
      ACTUAL -
      Process freezes. I dont get any error message or crash log. If there's anything I can do to provide more information or better debug the issue please let me know

      ---------- BEGIN SOURCE ----------
      //1 - loading the dll from inside the game
      typedef struct
      {
      void (*OnServerStart)(void);
      } ServerFunctions;

      typedef void (*PluginInit)(ServerFunctions* Funcs);

      uint32 MyThread::Run()
      {

      HINSTANCE hGetProcIDDLL = LoadLibrary(
      L"C:\\myDll.dll");

      PluginInit ExternalFunction = (PluginInit)GetProcAddress(hGetProcIDDLL, "PluginInit");
      ServerFunctions Functions = ServerFunctions();
      ExternalFunction(&Functions);
      FreeLibrary(hGetProcIDDLL);
      return 0;
      }


      //2 - main.cpp - dll entry point

      ServerFunctions* Server;
      JavaLoader* javaLoader;


      extern "C" EXPORT void PluginInit(ServerFunctions * functions) {

        javaLoader = new JavaLoader();
        javaLoader->StartJVM("path/to/jvm.dll");

      }

      //3 - javaLoader.h

      #pragma once
      #include <jni.h>

      typedef jint(JNICALL* JNIFUNC_CreateJavaVM) (JavaVM** pvm, void** penv, void* args);
      typedef jint(JNICALL* JNIFUNC_GetDefaultJavaVMInitArgs) (void* args);

      class JavaLoader
      {



      public:
      JavaLoader(void);
      void StartJVM(const char* path);


      private:


      JavaVMInitArgs vm_args;
      JNIFUNC_CreateJavaVM functionCreateJavaVM;
      JNIFUNC_GetDefaultJavaVMInitArgs functionGetDefaultJavaVMInitArgs;

      };

      //4 - JavaLoader.cpp

      JavaLoader::JavaLoader(void)
      {

      functionCreateJavaVM = nullptr;
      functionGetDefaultJavaVMInitArgs = nullptr;
      memset(&vm_args, 0, sizeof(vm_args));
      }


      JavaLoader::StartJVM(const char* path){

      HMODULE jvmModule = LoadLibraryA(path);
      if (jvmModule == nullptr) {

      printf("\n\nFAILED TO LOAD JVM LIBRARY AT: %s\n\n", path);
      exit(EXIT_FAILURE);
      return;
      }


      functionCreateJavaVM = (JNIFUNC_CreateJavaVM)Platform::LoadFunctionFromBinary(jvmModule, "JNI_CreateJavaVM");
      functionGetDefaultJavaVMInitArgs = (JNIFUNC_GetDefaultJavaVMInitArgs)Platform::LoadFunctionFromBinary(jvmModule, "JNI_GetDefaultJavaVMInitArgs");


      //======================= load arguments ==========================
      JavaVMInitArgs vm_args;
      vm_args.version = JNI_VERSION_1_6;

      jint result = functionGetDefaultJavaVMInitArgs(&vm_args);
      if (result != JNI_OK) {
      printf("functionGetDefaultJavaVMInitArgs error %d" + result);
      exit(EXIT_FAILURE);
      }

      vm_args.ignoreUnrecognized = false;


      const char* jarPath = "-Djava.class.path=C:\\path\\to\\jar";
      char* jpath = (char*)jarPath;

      JavaVMOption* options = new JavaVMOption[3];
      options[0].optionString = jpath;
      options[0].extraInfo = nullptr;
      options[1].optionString = (char*)"-Xmx256m";
      options[1].extraInfo = nullptr;
      options[2].optionString = (char*)"-Xcheck:jni";
      options[2].extraInfo =nullptr;

      vm_args.nOptions = 3;
      vm_args.options = options;

      //========================= create jvm ==========================
      JavaVM* jvm;
      JNIEnv* env;

      jint rc = functionCreateJavaVM(&jvm, (void**)&env, &vm_args); //process freezes here

      //does not reach this line
      delete options;

      }

      ---------- END SOURCE ----------

      FREQUENCY : often


            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: