我正在用C编写用于Windows的Java启动器,以针对位于程序目录中的Java运行时环境启动(即随程序一起分发)。我有运行正常的代码(在下面指定),但是它需要jvm.dll
在其%PATH%中才能执行。
我想在代码中添加一行代码,告诉程序为<executable's directory>/jre/bin/server
签入jvm.dll
,因此只需双击即可运行可执行文件。
现在,当我运行它时,它显示“该程序无法启动,因为您的计算机缺少jvm.dll。请尝试重新安装该程序以解决此问题。”
如果我将简单的可执行文件移到jre\bin\server
所在的jvm.dll
并尝试运行它,它将起作用。 所以我只需要告诉我的程序在其他特定位置搜索dll,就可以了。
根据我在搜索中发现的内容,我尝试了HINSTANCE hVM = LoadLibrary("jre\\bin\\server\\jvm.dll");
。不幸的是,这行不通。
我如何实现这个目标?我不是C程序员也不是Windows程序员,所以如果这个问题很基本,我深表歉意。
#include <jni.h>
#include <windows.h>
int main() {
HINSTANCE hVM = LoadLibrary("jre\\bin\\server\\jvm.dll"); //Does not work
JavaVM *jvm;
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption* options = new JavaVMOption[1];
int index = 0;
options[index].optionString = (char *)"-Djava.class.path=./main.jar";
vm_args.version = JNI_VERSION_10;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
delete options;
jmethodID main = NULL;
jclass cls = NULL;
cls = env->FindClass("net/joshuad/test/Main");
if(env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
if (cls != NULL) {
main = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
} else {
printf("Unable to find the requested class\n");
}
if (main != NULL) {
env->CallStaticVoidMethod( cls, main, " ");
} else {
printf("main method not found") ;
}
jvm->DestroyJavaVM();
return 0;
}
答案 0 :(得分:0)
仅当您将程序编写在包含jre文件夹的同一目录中时,给定路径才有效。否则,您将必须指定完整位置,例如“ C:\\ jdk \\ jrebin \ server \\ jvm.dll”
答案 1 :(得分:0)
我知道了。为了以这种方式链接到嵌入式JRE,我们需要link explicitly而不是隐式地,因此我们的程序在运行之前不会尝试进行链接,然后使用函数指针而不是调用JNI_CreateJavaVM
直接调用函数。
公平的免责声明-我是一位糟糕的C ++程序员,尽管这行得通,但我不知道它是否使用了良好的做法。使用后果自负。
这是其他可能尝试这样做的人的有效示例:
#include <jni.h>
#include <windows.h>
typedef UINT (CALLBACK* JVMDLLFunction)( JavaVM**, void**, JavaVMInitArgs * );
int main() {
HINSTANCE jvmDLL = LoadLibrary(".\\jre\\bin\\server\\jvm.dll");
if ( !jvmDLL ) {
printf("failed to find jvm.dll at specified location, exiting.\n");
return 1;
}
JVMDLLFunction createJavaVMFunction = (JVMDLLFunction)GetProcAddress(jvmDLL, "JNI_CreateJavaVM");
if ( ! createJavaVMFunction ) {
printf("Failed to get pointer to JNI_CreateJavaVM function from jvm.dll, exiting\n");
return 1;
}
JavaVM *jvm;
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption* options = new JavaVMOption[1];
int index = 0;
options[index].optionString = (char *)"-Djava.class.path=./main.jar";
vm_args.version = JNI_VERSION_10;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
createJavaVMFunction( &jvm, (void**)&env, &vm_args );
//JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
delete options;
jmethodID main = NULL;
jclass cls = NULL;
cls = env->FindClass("net/joshuad/test/Main");
if(env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
if (cls != NULL) {
main = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
} else {
printf("Unable to find the requested class\n");
}
if (main != NULL) {
env->CallStaticVoidMethod( cls, main, " ");
} else {
printf("main method not found") ;
}
jvm->DestroyJavaVM();
return 0;
}