如何防止JNI C++程序在其启动的JVM运行Java线程时退出?
防止C++程序在JVM线程运行时退出的解决方案
要避免C程序在Java线程仍运行时退出,核心是让C主线程等待Java线程执行完毕,以下是几种可行方案:
方案一:通过Java静态标志位同步
- 在你的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(); } }
- 在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()方法阻塞等待线程完成:
- 修改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(); } }
- 在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
相关产品推荐
相关产品推荐

