如何使用 JNI 而无需将 jvm.dll 位置添加到环境变量路径中

问题描述 投票:0回答:1

使 JNI 工作的一种方法是进入

Environment Variables
并添加到
User
System
Path
jvm.dll
所在的文件夹 (
.../bin/server
)。但这意味着在客户端计算机上,当您的应用程序启动时,您需要检查是否添加了路径,如果没有,则添加它。

但是您可以不这样做,而是将位置提供给

JavaVMOption
,或者使用其他方式,但在代码内部,而不必将该位置添加到
Environment Variables

我正在使用

Eclipse Adoptium
,它将与具有许可协议的应用程序文件一起添加,因此该位置将取决于应用程序的放置/安装位置,使得带有
Environment Variables
的选项有点烦人,因为该位置可能更改,因此在这种情况下每次都需要删除旧的并添加新的。

这就是我用来创建

JVM
的方法,其中
javaLocation
std::string
,它作为包含应用程序文件夹位置的函数的参数给出:

    javaLocation.insert(0, "-Djava.class.path=");
    javaLocation.append("Data\\Java");
    JavaVMInitArgs vm_args;
    JavaVMOption* options = new JavaVMOption[1];
    options[0].optionString = &javaLocation[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";

这个问题之前在this线程中被问过,并被标记为“这个问题已经有答案在这里”,但不幸的是,那里给出的答案不适用于JNI,它是DLL文件的通用解决方案.

java c++ windows java-native-interface
1个回答
0
投票

使用@Botje给出的建议(谢谢!),我再次尝试使用

LoadLibraryA
,这次我成功了:

#include <string>
#include <iostream>
#include <chrono>
#include <thread>
#include <jni.h>
#include <Windows.h>

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("D:\\Program Files\\MyApp\\").c_str() << std::endl;
    if (jvm != NULL) {
        std::cout << createIdentification().c_str();
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.