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

jvm.dll is loaded but GetProcAddress(hVM, "JNI_CreateJavaVM") returns 0

XMLWordPrintable

    • x86_64
    • windows_7

      ADDITIONAL SYSTEM INFORMATION :
      Windows 7 64-Bit

      A DESCRIPTION OF THE PROBLEM :
      With C++ CLI, for loading jvm.dll, i'm using below code.

      int hVM = LoadLibrary("jvm.dll");
      int fptr = GetProcAddress(hVM, "JNI_CreateJavaVM");
      res = ((JInvokeFn)fptr)(&jvm, (void**)&env, &vm_args);

      Load library returns handle but GetProcAddress returns 0. This code is working properly with Java 8.

      REGRESSION : Last worked in version 8u201

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      int hVM = LoadLibrary(jvmPath);
      int fptr = GetProcAddress(hVM, "JNI_CreateJavaVM");
      res = ((JInvokeFn)fptr)(&jvm, (void**)&env, &vm_args);
      if (res < 0) {
      System::Windows::Forms::MessageBox::Show("Can't create Java VM");
              fprintf(stderr, "Can't create Java VM\n");
              //exit(1);
      }

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      GetProcAddress(hVM, "JNI_CreateJavaVM") should retrun proper value.
      ACTUAL -
      GetProcAddress(hVM, "JNI_CreateJavaVM") returns 0

      ---------- BEGIN SOURCE ----------
      #include "StdAfx.h"
      #include "jni.h"
      #include "JavaWrapper.h"
      #include "ENOIEFEnvironment.h"
      #include <string>

      #include <msclr\marshal_cppstd.h>

       JNIEnv *env;
       JavaVM *jvm;
       jobject obj;
       jclass cls;

      [System::Runtime::InteropServices::DllImport("kernel32.dll", EntryPoint = "LoadLibraryA")]
      extern int LoadLibrary(System::String^ libFileName);

      [System::Runtime::InteropServices::DllImport("kernel32.dll", EntryPoint = "SetDllDirectoryA")]
      extern int SetDllDirectory(System::String^ dirName);

      [System::Runtime::InteropServices::DllImport("kernel32.dll", EntryPoint = "SetCurrentDirectoryA")]
      extern int SetCurrentDirectory(System::String^ dirName);

      [System::Runtime::InteropServices::DllImport("kernel32.dll", CharSet = System::Runtime::InteropServices::CharSet::Ansi)]
      extern int GetProcAddress(int hwnd, System::String^ functionName);

      [System::Runtime::InteropServices::DllImport("kernel32.dll", CharSet = System::Runtime::InteropServices::CharSet::Auto)]
      extern int GetShortPathName(System::String^ longPath, System::Text::StringBuilder^ shortPath, int shortPathLength);

      typedef jint (*JInvokeFn) (JavaVM **jvm, void **env, void *vm_args);


      JavaWrapper::JavaWrapper(System::Windows::Forms::Form^ formObj, System::String^ configFileName, System::String^ homeFolder)
      {
          currentFormObj = formObj;
          this->homeFolder= "";
          if (homeFolder != nullptr)
              this->homeFolder = homeFolder;

          System::String ^ iefClientRegistryKey = "SOFTWARE\\Dassault Systemes\\IEFClient";
          System::String^ Location = (System::String^)Microsoft::Win32::Registry::LocalMachine->OpenSubKey(iefClientRegistryKey)->GetValue("Location");
              
          decEnvFile = Location + "\\..\\CATEnv\\Env.txt";
          decEngineFolder = Location + "\\docs\\java";
          decDirectory = Location;

          if (configFileName == nullptr)
              decConfigFile = decDirectory + "\\reffiles\\IEFClientWorkspaceService\\config.xml";
          else
              decConfigFile = configFileName;
      }

      bool JavaWrapper::startEngine()
      {

      System::Windows::Forms::MessageBox::Show("Inside startEngine method");

          bool engineStarted = false;
          jint res;
          jmethodID mid;
          //jclass stringClass;
          //jobjectArray joArgs;

          System::String^ classpathOption = "-Djava.class.path=" + decEngineFolder + "\\IEFClientWorkspaceService.jar;"
              + decEngineFolder + "\\FCSClient.jar";

          System::Xml::XmlDocument^ config = gcnew System::Xml::XmlDocument();
          try
          {
              config->Load(decConfigFile);
          }
          catch(System::Xml::XmlException^ e)
          {
              // TODO: NLS Support
           (void)e;
              System::Windows::Forms::MessageBox::Show("Error occured while reading Config xml. Please check if values in this file are proper");
              return engineStarted;
          }

      System::Windows::Forms::MessageBox::Show("No issue with config.xml file");

          System::Xml::XmlNodeList^ LanguageList = config->GetElementsByTagName("language");
          System::String^ language = LanguageList->Item(0)->InnerText;

          msclr::interop::marshal_context context;
          string sDecEnvFile = context.marshal_as<std::string>(decEnvFile);
          ENOIEFEnvironment envObject(sDecEnvFile);
          std::string sJavaHome = envObject.GetEnv("JAVA_HOME");

          System::String^ javaHomeTemp = gcnew System::String(sJavaHome.c_str());
          System::String^ javaHome = gcnew System::String(sJavaHome.c_str());

      System::Windows::Forms::MessageBox::Show("javaHome: '" + javaHome + "'");
          
          System::String^ jvmPath = "jvm.dll";
          System::String^ jreBinPath = ".";

          if(!System::String::IsNullOrEmpty(javaHome))
          {
              jreBinPath = javaHome + "\\bin";
              jvmPath = javaHome + "\\bin\\client\\jvm.dll";
              if(!System::IO::File::Exists(jvmPath))
              {
                  jvmPath = javaHome + "\\bin\\server\\jvm.dll";
                  if(!System::IO::File::Exists(jvmPath))
                  {
                      // TODO: NLS Support
                      System::String^ errorMsg = "IEC cannot locate java install folder:\n" + javaHomeTemp + "\nPlease make sure, you have your java path correctly set in your Env.txt configuration file.";
                      System::Windows::Forms::MessageBox::Show(errorMsg,
                          "3DEXPERIENCE", System::Windows::Forms::MessageBoxButtons::OK,
                          System::Windows::Forms::MessageBoxIcon::Exclamation);
                      return engineStarted;
                  }
              }
          }
          else
          {
              // TODO: NLS Support
              System::String^ errorMsg = "JAVA_HOME is not defined in ENV.txt configuration file.";
              System::Windows::Forms::MessageBox::Show(errorMsg,
                  "3DEXPERIENCE", System::Windows::Forms::MessageBoxButtons::OK,
                  System::Windows::Forms::MessageBoxIcon::Exclamation);
              return engineStarted;
          }

      System::Windows::Forms::MessageBox::Show("jreBinPath: '" + jreBinPath + "'");

      System::Windows::Forms::MessageBox::Show("jvmPath: '" + jvmPath + "'");

          System::Xml::XmlNodeList^ javaOptionsList = config->GetElementsByTagName("javaoptions");

          System::String^ javaOptions = "";
          if(javaOptionsList->Count > 0)
              javaOptions = javaOptionsList->Item(0)->InnerText;

          //IR-538959: resolved cli for migration to ".NET Framework 4.6.2"
          cli::array<System::Char>^chars = {'-'};

          cli::array<System::String^>^ javaOptionsArray = javaOptions->Split(chars);

          System::Collections::ArrayList^ javaOptionsListArray = gcnew System::Collections::ArrayList();

          bool minHeapParamAdded = false;
          bool maxHeapParamAdded = false;
          //bool compilerOptionAdded = false;
          bool classPathOptionAdded = false;

          System::Collections::IEnumerator^ javaOptionsEnum = javaOptionsArray->GetEnumerator();
          while ( javaOptionsEnum->MoveNext() )
          {
              System::String^ javaOptionString = safe_cast<System::String^>(javaOptionsEnum->Current);

              javaOptionString = "-" + javaOptionString->Trim();

              if (!javaOptionString->Equals("-"))
              {
                  javaOptionsListArray->Add(javaOptionString);

                  if(javaOptionString->StartsWith("-Xms"))
                  {
                      minHeapParamAdded = true;
                  }
                  else if(javaOptionString->StartsWith("-Xmx"))
                  {
                      maxHeapParamAdded = true;
                  }
                  /*else if(javaOptionString->StartsWith("-Djava.compiler"))
                  {
                  compilerOptionAdded = true;
                  }*/
                  else if(javaOptionString->StartsWith("-Djava.class.path"))
                  {
                      classPathOptionAdded = true;
                  }
              }
          }

          if(!minHeapParamAdded)
          {
              javaOptionsListArray->Add("-Xms64m");
          }

          if(!maxHeapParamAdded)
          {
              javaOptionsListArray->Add("-Xmx64m");
          }
          /*
          if(!compilerOptionAdded)
          {
          javaOptionsListArray->Add("-Djava.compiler=NONE");
          }
          */
          if(!classPathOptionAdded)
          {
              javaOptionsListArray->Add(classpathOption);
          }

          JavaVMOption *options = new JavaVMOption[javaOptionsListArray->Count];

          System::Collections::IEnumerator^ javaOptionsEnumFinal = javaOptionsListArray->GetEnumerator();

          int i = 0;

          while ( javaOptionsEnumFinal->MoveNext() )
          {
              System::String^ javaOptionString = safe_cast<System::String^>(javaOptionsEnumFinal->Current);

              javaOptionString = javaOptionString->Trim();

              if (!javaOptionString->Equals("-"))
              {
                  options[i].optionString = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(javaOptionString);
                  i++;
              }
          }

          JavaVMInitArgs vm_args;

          vm_args.version = JNI_VERSION_1_4;
          vm_args.options = options;
          vm_args.nOptions = javaOptionsListArray->Count;
          vm_args.ignoreUnrecognized = JNI_TRUE;

      System::Windows::Forms::MessageBox::Show("Java VM creation started");

      SetCurrentDirectory(jreBinPath);

      SetDllDirectory(jreBinPath);

      int hVM = LoadLibrary(jvmPath);
      System::Windows::Forms::MessageBox::Show("LoadLibrary return int hVM: '" + hVM + "'");

      int fptr = GetProcAddress(hVM, "JNI_CreateJavaVM");
      System::Windows::Forms::MessageBox::Show("GetProcAddress return int fptr: '" + fptr + "'");

      res = ((JInvokeFn)fptr)(&jvm, (void**)&env, &vm_args);

      System::Windows::Forms::MessageBox::Show("Java VM creation completed");

          if (res < 0) {
      System::Windows::Forms::MessageBox::Show("Can't create Java VM");
              fprintf(stderr, "Can't create Java VM\n");
              //exit(1);
          }

          cls = (*env).FindClass("com/matrixone/MCADIntegration/client/engine/DSCEngine");
          if (cls == NULL) {
              stopEngine();
          }

          mid = (*env).GetMethodID(cls, "<init>", "()V");
          if (mid == NULL) {
              stopEngine();
          }

      System::Windows::Forms::MessageBox::Show("Java VM creation completed");

          obj = (*env).NewObject(cls, mid);
          mid = (*env).GetMethodID(cls, "initEngine", "(Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");

          const jchar* pDECDirectory = (const jchar*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalUni(decDirectory);
          jstring jDecDirectory = (*env).NewString(pDECDirectory,decDirectory->Length);

          const jchar* decConfigFileCharArr = (const jchar*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalUni(decConfigFile).ToPointer();
          jstring jConfigFilePath = (*env).NewString(decConfigFileCharArr,decConfigFile->Length);

          const jchar* pLanguage = (const jchar*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalUni(language);
          jstring jLanguage = (*env).NewString(pLanguage,language->Length);

          const jchar* pHomeFolder = (const jchar*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalUni(homeFolder);
          jstring jHomeFolder = (*env).NewString(pHomeFolder,homeFolder->Length);

          System::String ^ portFileName = DEFAULT_PORT_FILE_NAME;
          const jchar* pPortFileName = (const jchar*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalUni(portFileName);
          jstring jPortFileName;
          jPortFileName = (*env).NewString(pPortFileName,portFileName->Length);

          jstring jstr = (jstring)(*env).CallObjectMethod(obj,
              mid,
              jDecDirectory,
              jConfigFilePath,
              false,
              jLanguage,
              jHomeFolder,
              jPortFileName);

          System::String^ startupMessage = gcnew System::String((*env).GetStringUTFChars(jstr, (jboolean)false));

          if(!startupMessage->Equals(gcnew System::String("TRUE")))
          {
              System::String^ errorCode = startupMessage->Substring(0,startupMessage->IndexOf("|"));
              System::String^ errorMessage = startupMessage->Substring(startupMessage->IndexOf("|") + 1);
              if(!errorCode->Equals(gcnew System::String("IEF0011000019")))
              {
                  System::Windows::Forms::MessageBox::Show(gcnew System::String(errorMessage), "IEFClientWorkspaceService");
              }
              else
              {
                  // TODO: NLS Support
                  System::Windows::Forms::MessageBox::Show("Error while connecting to server. Please verify server url");
              }
          }
          else
          {
              engineStarted = true;
          }

          delete [] options;
          return engineStarted;
      }

      bool JavaWrapper::isShutdownEngine()
      {
           bool retVal = false;

           if(env == NULL)
               return true;

           jmethodID mid = (*env).GetMethodID(cls, "isShutdownEngine", "()Z");
           jboolean currentStatus = (*env).CallBooleanMethod(obj,mid);

           if(currentStatus)
           {
               stopEngine();
               retVal = true;
           }

           return retVal;
      }

      void JavaWrapper::stopEngine()
      {
          jmethodID mid = (*env).GetMethodID(cls, "stopEngine", "()V");
          (*env).CallObjectMethod(obj,mid);

          /*if ((*env).ExceptionOccurred())
          {
           (*env).ExceptionDescribe();
          }*/
          
          //(*jvm).DestroyJavaVM();
      }
      System::String^ JavaWrapper::getResourceString(System::String^ StringName)
      {
          
           char* pStringName = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(StringName);
           jstring jstringName;
           jstringName = (*env).NewStringUTF(pStringName);
           jmethodID mid = (*env).GetMethodID(cls, "getResourceString", "(Ljava/lang/String;)Ljava/lang/String;");
           jstring stringValue = (jstring)(*env).CallObjectMethod(obj,mid,jstringName);

          return gcnew System::String((const wchar_t *)((*env).GetStringChars(stringValue, (jboolean)false)));
      }

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

      FREQUENCY : always


            fmatte Fairoz Matte
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: