You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止JNI C++程序在其启动的JVM运行Java线程时退出?

防止C++程序在JVM线程运行时退出的解决方案

要避免C程序在Java线程仍运行时退出,核心是让C主线程等待Java线程执行完毕,以下是几种可行方案:

方案一:通过Java静态标志位同步

  1. 在你的Java类中添加一个volatile静态变量,用于标记线程运行状态:
public class YourJavaClass {
    public static volatile boolean threadRunning = true;

    public static void startWorkerThread() {
        new Thread(() -> {
            try {
                // 此处编写Java线程的业务逻辑
                Thread.sleep(5000); // 模拟任务执行
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                threadRunning = false; // 线程结束后更新标志位
            }
        }).start();
    }
}
  1. 在C++代码中,启动Java线程后循环检查这个标志位,直到线程结束:
#include <jni.h>
#include <iostream>
#include <chrono>
#include <thread>

using namespace std; // 修正原代码的大小写错误(Using → using)

int main()
{
    JavaVM *jvm;
    JNIEnv *env;
    JavaVMInitArgs vm_args;
    JavaVMOption* options = new JavaVMOption[1];
    options[0].optionString = "-Djava.class.path=.";
    vm_args.version = JNI_VERSION_1_6;
    vm_args.nOptions = 1;
    vm_args.options = options;
    vm_args.ignoreUnrecognized = false;

    jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
    delete options;
    if (rc != JNI_OK) {
        cin.get();
        exit(EXIT_FAILURE);
    }
    cout << "JVM load succeeded!\n";

    // 1. 获取目标Java类
    jclass javaClass = env->FindClass("YourJavaClass");
    if (javaClass == nullptr) {
        cerr << "Failed to find class!" << endl;
        jvm->DestroyJavaVM();
        return EXIT_FAILURE;
    }

    // 2. 调用静态方法启动Java线程
    jmethodID startMethod = env->GetStaticMethodID(javaClass, "startWorkerThread", "()V");
    if (startMethod == nullptr) {
        cerr << "Failed to find method!" << endl;
        jvm->DestroyJavaVM();
        return EXIT_FAILURE;
    }
    env->CallStaticVoidMethod(javaClass, startMethod);

    // 3. 获取静态标志位,循环等待线程结束
    jfieldID runningField = env->GetStaticFieldID(javaClass, "threadRunning", "Z");
    if (runningField == nullptr) {
        cerr << "Failed to find field!" << endl;
        jvm->DestroyJavaVM();
        return EXIT_FAILURE;
    }

    while (env->GetStaticBooleanField(javaClass, runningField)) {
        // 短暂休眠避免空转占用CPU
        this_thread::sleep_for(chrono::milliseconds(100));
    }

    jvm->DestroyJavaVM();
    return EXIT_SUCCESS;
}

方案二:调用Java线程的join()方法等待

如果Java代码中保留线程实例的引用,C++可以直接调用join()方法阻塞等待线程完成:

  1. 修改Java类,保存线程实例并提供等待方法:
public class YourJavaClass {
    private static Thread workerThread;

    public static void startWorkerThread() {
        workerThread = new Thread(() -> {
            // 线程业务逻辑
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        workerThread.start();
    }

    public static void waitForThread() throws InterruptedException {
        workerThread.join();
    }
}
  1. 在C++中调用等待方法:
// ... 前面的JVM初始化代码 ...

// 启动线程后,调用等待方法阻塞主线程
jmethodID waitMethod = env->GetStaticMethodID(javaClass, "waitForThread", "()V");
if (waitMethod != nullptr) {
    env->CallStaticVoidMethod(javaClass, waitMethod);
    // 处理可能的异常
    if (env->ExceptionCheck()) {
        env->ExceptionDescribe();
        env->ExceptionClear();
    }
}

// ... 后续销毁JVM代码 ...

关键注意事项

  • Java中的标志位必须用volatile修饰,保证多线程下的变量可见性。
  • 循环等待时加入短暂休眠,避免CPU空转浪费资源。
  • 调用JNI方法后要检查异常,防止程序因未处理的Java异常崩溃。

内容的提问来源于stack exchange,提问作者PelaRobsC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 08:25:30