JNI回调用中不同线程的env无法找到正确的kotlin的class

不同线程都需要通过 JavaVM 获取到的 JNIEnv 指针, 如果有两个线程有两个 env。 其中一个是jni接口自己传过来的,可以正常使用,正常获取kotlin中的class。但是通过 JavaVM 新获取的env 无法找到kotlin的class

1. 确保线程已附加到 JVM

确保每个线程在使用 JNIEnv 之前已附加到 JVM。可以在每个线程中调用 AttachCurrentThread

cpp 复制代码
JavaVM* g_jvm = nullptr;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
    g_jvm = vm;
    return JNI_VERSION_1_6;
}

void someJNIFunction() {
    JNIEnv* env;
    if (g_jvm->AttachCurrentThread(&env, nullptr) != JNI_OK) {
        // 处理错误
        return;
    }

    // 使用 env 进行 JNI 调用
    jclass cls = env->FindClass("com/example/YourKotlinClass");
    if (cls == nullptr) {
        // 处理类未找到的错误
    }

    // 线程使用完成后,分离线程
    g_jvm->DetachCurrentThread();
}

2. 确保正确缓存类引用(关键:类要转化成全局引用即可给不同env使用)

确保类引用被正确缓存,并且在不同的线程中可用。可以在 JNI_OnLoad 中缓存类引用:

cpp 复制代码
jclass g_yourKotlinClass; //这里是关键

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
    g_jvm = vm;
    JNIEnv* env;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }

		// 这部分代码也可以写在 someJNIFunction 内。 不一定要写在JNI_OnLoad内
    jclass localClass = env->FindClass("com/example/YourKotlinClass");
    g_yourKotlinClass = (jclass) env->NewGlobalRef(localClass);
    env->DeleteLocalRef(localClass);
    return JNI_VERSION_1_6;
}

3. 例子:完整示例代码

cpp 复制代码
#include <jni.h>
#include <android/log.h>

#define LOG_TAG "JNI_OnLoad"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)

JavaVM* g_jvm = nullptr;
jclass g_yourKotlinClass = nullptr;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
    g_jvm = vm;
    JNIEnv* env;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }

    jclass localClass = env->FindClass("com/example/YourKotlinClass");
    if (localClass == nullptr) {
        return JNI_ERR; // 类加载失败
    }

    g_yourKotlinClass = (jclass) env->NewGlobalRef(localClass);
    env->DeleteLocalRef(localClass);
    return JNI_VERSION_1_6;
}

void someJNIFunction() {
    JNIEnv* env;
    if (g_jvm->AttachCurrentThread(&env, nullptr) != JNI_OK) {
        // 处理错误
        return;
    }

    if (g_yourKotlinClass == nullptr) {
        LOGD("Kotlin class is null");
        return;
    }

    jmethodID methodID = env->GetMethodID(g_yourKotlinClass, "yourMethodName", "()V");
    if (methodID == nullptr) {
        LOGD("Method ID not found");
        return;
    }

    jobject obj = ... // 获取对象实例
    env->CallVoidMethod(obj, methodID);

    g_jvm->DetachCurrentThread();
}
相关推荐
How_doyou_do20 分钟前
数据传输优化-异步不阻塞处理增强首屏体验
开发语言·前端·javascript
jingfeng51437 分钟前
C++11可变参数模板、emplace系列接口、包装器
开发语言·c++
云天徽上38 分钟前
【数据可视化-107】2025年1-7月全国出口总额Top 10省市数据分析:用Python和Pyecharts打造炫酷可视化大屏
开发语言·python·信息可视化·数据挖掘·数据分析·pyecharts
Tina表姐1 小时前
(C题|NIPT 的时点选择与胎儿的异常判定)2025年高教杯全国大学生数学建模国赛解题思路|完整代码论文集合
c语言·开发语言·数学建模
Kevinhbr1 小时前
CSP-J/S IS COMING
数据结构·c++·算法
蕓晨1 小时前
set的插入和pair的用法
c++·算法
金古圣人2 小时前
hot100 滑动窗口
数据结构·c++·算法·leetcode·哈希算法
蒹葭玉树2 小时前
【C++上岸】C++常见面试题目--算法篇(第二十期)
c++·算法·面试
轮到我狗叫了2 小时前
牛客.小红的子串牛客.kotori和抽卡牛客.循环汉诺塔牛客.ruby和薯条
java·开发语言·算法
yudiandian20142 小时前
【QT 5.12.12 下载 Windows 版本】
开发语言·qt