通过 JNI 部署 JRE:jvm.dll 并非设计用于 运行 on Windows or [......]

Deploying JRE via JNI: jvm.dll not designed to run on Windows or [......]

所以我正在创建一个 Win32 应用程序,它将 Java 运行时环境 (JRE) 打包为资源。应用程序将资源提取到磁盘并解压缩。现在,我想使用这个 JRE 来 运行 一个使用调用 API 的 Java 程序。一旦我将程序更改为指向提取的 JRE jvm.dll 而不是安装的 JRE(这是我复制的),我收到此错误:

<jre-path>\jre1.8.0_31\bin\server\jvm.dll is either not designed to run on Windows or it contains an error. Try installing the program again using the original installation media or contact your system administrator or the software vendor for support. Error status 0x000012f

我希望对这个问题做的是记录这个错误以及导致它的原因。如果可能,找到一个解决方案,以便我可以引用提取的 JRE。

让我给出我的环境的一些细节。首先,我是 运行ning Windows 10 Tech Preview。我的OS、我的程序、我安装复制过来的JRE都是64位的。另外,当我让我的程序指向已安装的 JRE 时,它工作正常,问题仅出在复制的 JRE 上。

还有一些代码供我参考:

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

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //For brevity I am omitting the extraction/unzipping.
    //I am using libzip to do the unzipping which uses zlib
    //for dealing with the compression/decrompression.
    //Likewise, I am also omitting the error checking for brevity.

    //Assume at this point the JRE folder exists in the same location
    //as this program's executable file.  I am accessing the jvm.dll
    //using a relative file path.

    //Load the Java virtual machine inside of the packaged JRE.
    //This is where that error occurs.
    //LoadLibrary is necessary because I must connect to the DLL after
    //it has been unpacked.
    HMODULE jvmDll = LoadLibrary(_T("jre1.8.0_31\bin\server\jvm.dll"));
    CreateJVMFunc CreateJVM = (CreateJVMFunc)GetProcAddress(jvmDll, "JNI_CreateJavaVM");

    //Start the Java virtual machine.
    JavaVM *jvm;
    JNIEnv *env;
    JavaVMInitArgs vmArgs;
    JavaVMOption *options = new JavaVMOption[1];
    options[0].optionString = "-Djava.class.path=C:/Users/Nicholas/Documents/Programming Projects/Java Projects/JVM Launcher Test/JVM Launcher Test.jar"
    vmArgs.version = JNI_VERSION_1_8;
    vmArgs.nOptions = 1;
    vmArgs.options = options;
    vmArgs.ignoreUnrecognized = false;

    int retVal = CreateJVM(&jvm, (void**)&env, &vmArgs);
    delete[] options;

    //Instantiate the program.
    jclass mainClass = env->FindClass("jvmlauncher/test/Application");
    jmethodID mainMethod = env->GetStaticMethodID(mainClass, "main", "([Ljava/lang/String;)V");
    env->CallStaticVoidMethod(mainClass, mainMethod, NULL);

    //Cleanup.
    jvm->DestroyJavaVM();
    FreeLibrary(jvmDll);
    return 0;
}

所以我想有几个问题我想找到答案。

What exactly triggers the error message? This error is not unique to my application, so what documentation exists for that error?

错误信息是对的。我的自定义安装出了点问题。显然,从可执行文件中提取文件时,文件丢失了数据。 直接复制到当前安装的JRE后,一切正常!

Why is the copied JRE (which is an exact copy of the installed one) not working as I expected?

因为它不是“精确”的副本。

How can I correct the situation so I can use this unpacked JRE?

这不再是问题,因为这是我的错。提取不正确。

PS:享受 JNI 代码,希望它能帮助以后的人做这件事!

只需安装 32 位 JDK 版本和 运行 Android Studio。
如果 Android Studio 未检测到 32 位 JDK 本身更改您的环境变量