Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Java
  4. How to use JNI without setting Environment Variables

How to use JNI without setting Environment Variables

Scheduled Pinned Locked Moved Java
c++javacomsysadmintutorial
6 Posts 2 Posters 11 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    Valentinor
    wrote on last edited by
    #1

    I found the following code posted by @Richard-MacCutchan to a thread about how to use JNI without having to add the location of jvm.dll into Environment Variables. I kinda understood how it works but still...

    /*
    ******************************************************************************
    *
    * Name : cpptojava.cpp
    *
    * Function : Basic Console application to call a Java class.
    *
    * Created : 09 Jun 2022
    *
    ******************************************************************************
    */

    #include
    #include
    #include
    #include
    #include
    #include // requires -std:c++17

    #include "jni.h"

    //
    // Find the path to the jvm.dll given the base path to the Java runtime (or JDK if installed)
    //
    HMODULE LoadDll(
    const char* jrePath
    )
    {
    const char* pszjvmname = "bin\\server\\jvm.dll"; // Java VM name
    HMODULE hJVMDLL = 0;

    std::filesystem::path jvmpath(jrePath);
    jvmpath /= pszjvmname;
    if (!std::filesystem::exists(jvmpath))
    {
        std::cerr << "JVM library " << jvmpath << " not found." << std::endl;
        // throw an exception 
    }
    
    // load the Java VM DLL into our address space
    // NB filesystem::path is Unicode
    hJVMDLL = LoadLibraryW(reinterpret\_cast(jvmpath.c\_str()));
    if (hJVMDLL != NULL)
    {
        std::clog << "jvm.dll loaded from: " << jvmpath << std::endl;
    }
    return hJVMDLL; // a Windows HANDLE to the DLL
    

    }

    //
    // A function to load the Java VM and initialise the JNI interface
    // There are a number of diagnostic messages to show progress
    //
    JNIEnv* AttachJVM(
    const char* jrePath,
    JavaVM* jvm,
    std::string strcwd
    )
    {
    HMODULE hJVMDLL = LoadDll(jrePath);
    if (hJVMDLL == 0)
    {
    return nullptr;
    }
    typedef jint(JNICALL* fpCJV)(JavaVM**, void**, void*);
    fpCJV JNI_CreateJavaVM = (fpCJV)::GetProcAddress(hJVMDLL, "JNI_CreateJavaVM");

    // tell the JVM where to find the class
    JavaVMOption    options\[2\];
    std::stringstream ssoptions;
    ssoptions << "-Djava.class.path=";
    ssoptions << strcwd;
    std::string stropts = ssoptions.str();
    options\[0\].optionString = const\_cast(stropts.c\_str());
    options\[1\].optionString = const\_cast("-verbose:jni");   // print JNI-related messages
    
    JavaVMInitArgs  vm\_args; // JDK/JRE 6 VM initialization
    
    V J 2 Replies Last reply
    0
    • V Valentinor

      I found the following code posted by @Richard-MacCutchan to a thread about how to use JNI without having to add the location of jvm.dll into Environment Variables. I kinda understood how it works but still...

      /*
      ******************************************************************************
      *
      * Name : cpptojava.cpp
      *
      * Function : Basic Console application to call a Java class.
      *
      * Created : 09 Jun 2022
      *
      ******************************************************************************
      */

      #include
      #include
      #include
      #include
      #include
      #include // requires -std:c++17

      #include "jni.h"

      //
      // Find the path to the jvm.dll given the base path to the Java runtime (or JDK if installed)
      //
      HMODULE LoadDll(
      const char* jrePath
      )
      {
      const char* pszjvmname = "bin\\server\\jvm.dll"; // Java VM name
      HMODULE hJVMDLL = 0;

      std::filesystem::path jvmpath(jrePath);
      jvmpath /= pszjvmname;
      if (!std::filesystem::exists(jvmpath))
      {
          std::cerr << "JVM library " << jvmpath << " not found." << std::endl;
          // throw an exception 
      }
      
      // load the Java VM DLL into our address space
      // NB filesystem::path is Unicode
      hJVMDLL = LoadLibraryW(reinterpret\_cast(jvmpath.c\_str()));
      if (hJVMDLL != NULL)
      {
          std::clog << "jvm.dll loaded from: " << jvmpath << std::endl;
      }
      return hJVMDLL; // a Windows HANDLE to the DLL
      

      }

      //
      // A function to load the Java VM and initialise the JNI interface
      // There are a number of diagnostic messages to show progress
      //
      JNIEnv* AttachJVM(
      const char* jrePath,
      JavaVM* jvm,
      std::string strcwd
      )
      {
      HMODULE hJVMDLL = LoadDll(jrePath);
      if (hJVMDLL == 0)
      {
      return nullptr;
      }
      typedef jint(JNICALL* fpCJV)(JavaVM**, void**, void*);
      fpCJV JNI_CreateJavaVM = (fpCJV)::GetProcAddress(hJVMDLL, "JNI_CreateJavaVM");

      // tell the JVM where to find the class
      JavaVMOption    options\[2\];
      std::stringstream ssoptions;
      ssoptions << "-Djava.class.path=";
      ssoptions << strcwd;
      std::string stropts = ssoptions.str();
      options\[0\].optionString = const\_cast(stropts.c\_str());
      options\[1\].optionString = const\_cast("-verbose:jni");   // print JNI-related messages
      
      JavaVMInitArgs  vm\_args; // JDK/JRE 6 VM initialization
      
      V Offline
      V Offline
      Valentinor
      wrote on last edited by
      #2

      I managed to make it work:

      #include
      #include
      #include
      #include
      #include
      #include

      JavaVM* jvm = nullptr;

      std::string createVM(std::string location) {
      std::string jvmLocation = location;
      jvmLocation.append("ThirdParty\\Eclipse Adoptium\\jre-17.0.7.7-hotspot\\bin\\servers\\jvm.dll");
      HMODULE hJVMDLL = LoadLibraryA(jvmLocation.c_str());
      typedef jint(JNICALL* fpCJV)(JavaVM**, void**, void*);
      if (hJVMDLL != NULL) {
      fpCJV JNI_CreateJavaVM = (fpCJV)::GetProcAddress(hJVMDLL, "JNI_CreateJavaVM");
      location.insert(0, "-Djava.class.path=");
      location.append("Data\\Java");
      JavaVMInitArgs vm_args;
      JavaVMOption* options = new JavaVMOption[1];
      options[0].optionString = &location[0];
      vm_args.version = JNI_VERSION_10;
      vm_args.nOptions = 1;
      vm_args.options = options;
      vm_args.ignoreUnrecognized = false;
      JNIEnv* env = nullptr;
      jint rc = JNI_OK;
      if (jvm == nullptr) {
      rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
      }
      else {
      rc = jvm->AttachCurrentThread((void**)&env, NULL);
      }
      delete[] options;
      if (rc != JNI_OK) {
      if (rc == JNI_EVERSION)
      return "JNI_EVERSION";
      else if (rc == JNI_ENOMEM)
      return "JNI_ENOMEM";
      else if (rc == JNI_EINVAL)
      return "JNI_EINVAL";
      else if (rc == JNI_EEXIST)
      return "JNI_EEXIST";
      else
      return "JNI_FATALERROR";
      }
      return "JNI_CREATED";
      }
      else {
      return "ERROR_LOADING_DLL";
      }
      }

      std::string createIdentification() {
      JNIEnv* env;
      jvm->AttachCurrentThread((void**)&env, NULL);
      jclass jClass = env->FindClass("JavaMethods");

      if (jClass == nullptr) {
      	return "ClassNotFound cI";
      }
      else {
      	jmethodID methodID = env->GetStaticMethodID(jClass, "createIdentification", "()Ljava/lang/String;");
      	if (methodID == nullptr) {
      		return "MethodNotFound cI";
      	}
      	else {
      		jboolean isCopy;
      		jstring jResult = (jstring)env->CallStaticObjectMethod(jClass, methodID);
      		const char\* string = env->GetStringUTFChars(jResult, &isCopy);
      		std::string result = string;
      		env->ReleaseStringUTFChars(jResult, string);
      
      		return result;
      	}
      }
      

      }

      int main() {
      std::cout << createVM("Location_To_App_Folder").c_str() << std::endl;
      if (jvm != NULL) {
      std::cout << createIdentification().c_str();
      }

      std::this\_thread::sleep\_for(std::chrono::milliseconds(2000));
      return 0;
      

      }

      Thank you @Richard-MacCutchan for the or

      1 Reply Last reply
      0
      • V Valentinor

        I found the following code posted by @Richard-MacCutchan to a thread about how to use JNI without having to add the location of jvm.dll into Environment Variables. I kinda understood how it works but still...

        /*
        ******************************************************************************
        *
        * Name : cpptojava.cpp
        *
        * Function : Basic Console application to call a Java class.
        *
        * Created : 09 Jun 2022
        *
        ******************************************************************************
        */

        #include
        #include
        #include
        #include
        #include
        #include // requires -std:c++17

        #include "jni.h"

        //
        // Find the path to the jvm.dll given the base path to the Java runtime (or JDK if installed)
        //
        HMODULE LoadDll(
        const char* jrePath
        )
        {
        const char* pszjvmname = "bin\\server\\jvm.dll"; // Java VM name
        HMODULE hJVMDLL = 0;

        std::filesystem::path jvmpath(jrePath);
        jvmpath /= pszjvmname;
        if (!std::filesystem::exists(jvmpath))
        {
            std::cerr << "JVM library " << jvmpath << " not found." << std::endl;
            // throw an exception 
        }
        
        // load the Java VM DLL into our address space
        // NB filesystem::path is Unicode
        hJVMDLL = LoadLibraryW(reinterpret\_cast(jvmpath.c\_str()));
        if (hJVMDLL != NULL)
        {
            std::clog << "jvm.dll loaded from: " << jvmpath << std::endl;
        }
        return hJVMDLL; // a Windows HANDLE to the DLL
        

        }

        //
        // A function to load the Java VM and initialise the JNI interface
        // There are a number of diagnostic messages to show progress
        //
        JNIEnv* AttachJVM(
        const char* jrePath,
        JavaVM* jvm,
        std::string strcwd
        )
        {
        HMODULE hJVMDLL = LoadDll(jrePath);
        if (hJVMDLL == 0)
        {
        return nullptr;
        }
        typedef jint(JNICALL* fpCJV)(JavaVM**, void**, void*);
        fpCJV JNI_CreateJavaVM = (fpCJV)::GetProcAddress(hJVMDLL, "JNI_CreateJavaVM");

        // tell the JVM where to find the class
        JavaVMOption    options\[2\];
        std::stringstream ssoptions;
        ssoptions << "-Djava.class.path=";
        ssoptions << strcwd;
        std::string stropts = ssoptions.str();
        options\[0\].optionString = const\_cast(stropts.c\_str());
        options\[1\].optionString = const\_cast("-verbose:jni");   // print JNI-related messages
        
        JavaVMInitArgs  vm\_args; // JDK/JRE 6 VM initialization
        
        J Offline
        J Offline
        jschell
        wrote on last edited by
        #3

        Valentinor wrote:

        I'm not making them install Java

        That is oddly phrased since they will need to have java installed somehow. As a suggestion only you might want to work on your error handling if it turns out Java isn't installed. Telling a user that a dll is missing is not going to help them nor you when they ask why it isn't working. You might want to also print where you looked when you can't find it.

        V 1 Reply Last reply
        0
        • J jschell

          Valentinor wrote:

          I'm not making them install Java

          That is oddly phrased since they will need to have java installed somehow. As a suggestion only you might want to work on your error handling if it turns out Java isn't installed. Telling a user that a dll is missing is not going to help them nor you when they ask why it isn't working. You might want to also print where you looked when you can't find it.

          V Offline
          V Offline
          Valentinor
          wrote on last edited by
          #4

          jschell wrote:

          That is oddly phrased since they will need to have java installed somehow.

          Why did you stopped there with the quote? As the next part of the phrase contained the reason why I'm not making the install Java:

          Valentinor wrote:

          but it comes in the app files with a license agreement, I'm using Eclipse Adoptium (...\MyApp\ThirdParty\Eclipse Adoptium\jre-17.0.7.7-hotspot).

          So yeah, they don't need to install java, as it is included with the app.

          J 1 Reply Last reply
          0
          • V Valentinor

            jschell wrote:

            That is oddly phrased since they will need to have java installed somehow.

            Why did you stopped there with the quote? As the next part of the phrase contained the reason why I'm not making the install Java:

            Valentinor wrote:

            but it comes in the app files with a license agreement, I'm using Eclipse Adoptium (...\MyApp\ThirdParty\Eclipse Adoptium\jre-17.0.7.7-hotspot).

            So yeah, they don't need to install java, as it is included with the app.

            J Offline
            J Offline
            jschell
            wrote on last edited by
            #5

            Valentinor wrote:

            So yeah, they don't need to install java,

            On Windows a Java install consists basically of the following. 1. Lay down the files into the file system. 2. Create the registry data so the user can uninstall it. So apparently what you are actually doing is giving the user the option to use the Java that is already installed or to use the VM that comes with your application. Besides my other suggestion you might also want to consider whether the VM they have installed is the correct version for your appliction.

            V 1 Reply Last reply
            0
            • J jschell

              Valentinor wrote:

              So yeah, they don't need to install java,

              On Windows a Java install consists basically of the following. 1. Lay down the files into the file system. 2. Create the registry data so the user can uninstall it. So apparently what you are actually doing is giving the user the option to use the Java that is already installed or to use the VM that comes with your application. Besides my other suggestion you might also want to consider whether the VM they have installed is the correct version for your appliction.

              V Offline
              V Offline
              Valentinor
              wrote on last edited by
              #6

              jschell wrote:

              1. Lay down the files into the file system.

              Yes or no, depending what you mean by "file system". When the app is installed, inside it's folder structure it will also have Eclipse Adoptium (...\MyApp\ThirdParty\Eclipse Adoptium\jre-17.0.7.7-hotspot)

              jschell wrote:

              2. Create the registry data so the user can uninstall it.

              It will be for the app itself and not just for java, as Eclipse Adoptium will be a part of the app, integrated into it, and not separate. When the app is uninstalled, so will Eclipse Adoptium as it is part of its files. If the user has any other form of Java installed, they won't be affected in any way.

              jschell wrote:

              So apparently what you are actually doing is giving the user the option to use the Java that is already installed or to use the VM that comes with your application.

              No. The app will only use Java that comes with it, as the app won't even look in another location if Java is installed, only inside it's file structure.

              jschell wrote:

              whether the VM they have installed is the correct version for your appliction

              I explained in the above statement why this doesn't matter for my case.

              jschell wrote:

              As a suggestion only you might want to work on your error handling if it turns out Java isn't installed. Telling a user that a dll is missing is not going to help them nor you when they ask why it isn't working.

              I never said that I don't have an error handling system already added. If any of Java files are missing or are corrupted, or any of the other app files are missing or are corrupted, an error will appear telling the user to run the check for corrupted files or reinstall the app, accompanied by an error message, that will tell me exactly which file is the problem, if it is missing or if it is corrupted.

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups