首页 > 解决方案 > 如何使用C++ jni环境运行springboot应用

问题描述

我正在尝试使用以下代码使用 C++ jni lib 运行 springboot 应用程序 jar 文件:

void init_jni() {
    const int kNumOptions = 1;
    JavaVMOption options[kNumOptions] = {
            {const_cast<char *>("-Djava.class.path=app-0.0.1-SNAPSHOT.jar"), nullptr},
    };

    JavaVMInitArgs vmArgs = {
            JNI_VERSION_1_8, kNumOptions, options, JNI_TRUE
    };

    // Create the JVM
    JavaVM *javaVM;
    JNIEnv *jniEnv;

    long flag = JNI_CreateJavaVM(&javaVM, (void **) &jniEnv, &vmArgs);


    if (flag == JNI_ERR) {
        cout << "Error creating VM. Exiting...\n";
        exit(1);
    }

    jclass jcls = jniEnv->FindClass("org/springframework/boot/loader/JarLauncher");

    if (jcls == nullptr) {
        jniEnv->ExceptionDescribe();
        javaVM->DestroyJavaVM();
        exit(1);
    }

    jmethodID methodId = jniEnv->GetStaticMethodID(jcls, "main", "([Ljava/lang/String;)V");

    if (methodId == nullptr) {
        jniEnv->ExceptionDescribe();
        javaVM->DestroyJavaVM();
        exit(1);
    }


    jniEnv->CallStaticVoidMethod(jcls, methodId);

    if (jniEnv->ExceptionCheck()) {
        jniEnv->ExceptionDescribe();
        jniEnv->ExceptionClear();
    }


    javaVM->DestroyJavaVM();
}

当我调用init_jni上面的方法时,我得到了一个 java.lang.CloneNotSupportedException。java -jar app-0.0.1-SNAPSHOT.jar通过终端运行正常。还有什么我应该做的吗?

这是抛出的异常:

Exception in thread "main" java.lang.CloneNotSupportedException: java.lang.Class
    at java.lang.Object.clone(Native Method)
    at org.springframework.boot.loader.MainMethodRunner.<init>(MainMethodRunner.java:41)
    at org.springframework.boot.loader.Launcher.createMainMethodRunner(Launcher.java:99)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)

标签: javac++java-native-interface

解决方案


受到@Mister_Jeusu 评论的启发,我尝试了这个。它对我有用。

int RunSpring(JavaVM * jvm, JNIEnv * env)
{
        /* Run app */

        jclass class = (*env)->FindClass(env, "org/springframework/boot/loader/JarLauncher");
        if (!class)
        {
                PRINT_LINENO;
                return -1;
        }

        jmethodID mid = (*env)->GetStaticMethodID(env, class, "main", "([Ljava/lang/String;)V");
        if (!mid)
        {
                PRINT_LINENO;
                return -1;
        }

        (*env)->CallStaticVoidMethod(env, class, mid, NULL);

        return 0;
}

推荐阅读