模块中的Java JNI运行类

时间:2019-01-10 08:33:28

标签: java c++ java-native-interface

我正在尝试创建一个运行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可用的模块中获取类?

0 个答案:

没有答案