在JNI中,可以使用全局引用(Global Reference)来保存Java对象的引用。全局引用是一种特殊的引用类型,它可以在JNI环境中长期保存Java对象的引用,直到显式释放。
下面是一种在JNI中保存Java对象的简单示例:
-
首先,在JNI的头文件中声明一个全局变量用于保存对象的全局引用。
jobject callBack; jmethodID callMethod;
-
在JNI代码的实现中,通过NewGlobalRef函数将Java对象转换为全局引用,并将其保存到全局变量中。在适当的时候,可以使用DeleteGlobalRef函数释放全局引用
extern "C" JNIEXPORT void JNICALL Java_com_test_jnitest_TestLib_init(JNIEnv *env, jobject thiz, jobject call_back) { // 将Java对象转换为全局引用 callBack = env->NewGlobalRef(call_back); jclass callClass = env->GetObjectClass(callBack); callMethod = env->GetMethodID(callClass,"onData","(ILjava/lang/String;)V"); }
-
在需要使用保存的对象的地方,可以直接使用保存的全局引用进行操作。
下面举例在JNI中创建一个定时循环线程调用JAVA方法
// 线程函数,用于定时循环执行任务 void TimerLoop() { JNIEnv* env = AttachCurrentThreadIfNeeded(); while (isRunning) { // 执行需要循环的任务,例如调用Java方法 count++; jstring arg2 = env->NewStringUTF("HelloWorld"); env->CallVoidMethod(callBack, callMethod,count,arg2); env->DeleteLocalRef(arg2); // 线程休眠一段时间,例如1000毫秒 std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } g_vm->DetachCurrentThread(); } extern "C" JNIEXPORT void JNICALL Java_com_test_jnitest_TestLib_start(JNIEnv *env, jobject thiz) { // 检查线程是否已经在运行 if (isRunning) { return; } // 创建线程并开始运行 isRunning = true; timerThread = std::thread(TimerLoop); } extern "C" JNIEXPORT void JNICALL Java_com_test_jnitest_TestLib_stop(JNIEnv *env, jobject thiz) { // 停止线程运行 if (isRunning) { isRunning = false; env->DeleteGlobalRef(callBack); } }
在上面的示例代码中,我们首先定义了一个全局变量 timerThread 和一个标志 isRunning 来控制线程的运行状态。isRunning 变量用于在定时循环中控制任务的执行和线程的停止。在start函数中,我们通过创建一个新的标准库线程 (std::thread) 并传递 TimerLoop 函数作为线程函数来启动定时循环线程。在 stop 函数中,我们将 isRunning 设置为 false 来停止线程的运行,并等待线程结束。