我正在尝试创建一个运行Java项目的可执行文件,该文件类似于Launch4j和类似项目也可以。区别在于Launch4j仅启动.jar
,因此它将是它自己的过程。我想使用JNI创建JVM,以便可以完全控制项目线程,从而可以在本机上下文中进一步自定义程序外观。
我的Java项目使用jlink
进行编译,以为该项目创建自定义的最小运行时。如果有人不知道的话,这还将把Java项目本身也添加到运行时中。您可以尝试运行java.exe -m "project.module.name/project.module.name.Main"
,它将直接从运行时运行项目。
这基本上是我现在正在运行的C ++代码。
#include <iostream>
#include <windows.h>
#include <string>
#include <jni.h>
#include "resources.h"
int main () {
/* Used in production mode to avoid a console window
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow) {
*/
JavaVM *jvm; /* Java VM */
JNIEnv *env; /* Pointer to native method interface */
JavaVMInitArgs vm_args; /* VM initialization arguments */
vm_args.version = JNI_VERSION_10;
JavaVMOption* options = new JavaVMOption[0];
vm_args.nOptions = 0;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
HINSTANCE hinstLib = LoadLibrary(TEXT(".\\bin\\server\\jvm.dll")); /* Loads the custom jvm.dll created by jlink */
typedef jint(JNICALL *pCreateJavaVM)(JavaVM **, void**, void *); /* Defines jint */
pCreateJavaVM CreateJavaVM = (pCreateJavaVM)GetProcAddress(hinstLib, "JNI_CreateJavaVM"); /* Pointer to the JNI_CreateJavaVM function inside the custom jvm.dll */
jint res = CreateJavaVM(&jvm, (void**)&env, &vm_args); /* Create the java VM and save the success/fail result of starting it */
if (res < 0) { /* Negative values are errors */
std::cout << "Couldn't run VM. Error: " << res << std::endl;
delete options;
jvm->DestroyJavaVM();
return res;
} else {
/* This is where the crashing happens */
jclass clazz = env->FindClass("project.module.name.Main");
if (clazz == NULL) {
std::cout << "Couldn't find the class" << std::endl;
env->ExceptionDescribe();
jvm->DestroyJavaVM();
return -1;
} else {
jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;])V"); /* Get the main function of the class */
env->CallStaticVoidMethod(clazz, mid, ""); /* Run the main function */
delete options;
jvm->DestroyJavaVM();
}
}
std::cout << "Ending..." << std::endl;
return 0;
}
这会编译并运行到我得到以下错误为止:
Couldn't find the class
Exception in thread "main" java.lang.NoClassDefFoundError: project.module.name.Main
我最初的想法是,也许我需要做的是运行JVM,并将JVM的classpath设置为Java项目的jar版本的位置,但是由于运行时已经在其中包含了项目,所以这又不是必须的
是否可以使用可以与-m "project.module.name/project.module.name.Main"
一起使用的功能类似于java.exe
的选项来运行JVM?当然,这完全不起作用(我尝试过),因为这些是java.exe
的选项,而不是JVM的选项。我的意思是,如果java.exe
能做到,为什么我自己的可执行文件不能做到这一点?也许有一种方法可以从JVM可用的模块中获取类?