programing

비동기 콜용 JNI 인터페이스 포인터(JNIEnv *)를 얻는 방법

goodsources 2022. 8. 8. 20:07
반응형

비동기 콜용 JNI 인터페이스 포인터(JNIEnv *)를 얻는 방법

JNI 인터페이스 포인터(JNIEnv *)는 현재 스레드에서만 유효하다는 것을 알게 되었습니다.네이티브 메서드 내에서 새 스레드를 시작했다고 가정합니다. 이벤트를 Java 메서드로 비동기적으로 전송할 수 있는 방법은 무엇입니까?이 새 스레드는 (JNIEnv *)의 참조를 가질 수 없습니다.(JNIEnv *)에 대한 글로벌 변수를 저장하는 것이 작동하지 않는 것 같습니다.

JVM에 대한 포인터를 얻을 수 있습니다( ).JavaVM*이 포인터는 글로벌 변수로 안전하게 저장할 수 있습니다.나중에 새로운 스레드에서는 새로운 스레드를 C/C++로 작성한 경우 또는 단순히 JNI가 사용자에게 전달하기 때문에 상정하지 않은 Java 코드로 스레드를 작성한 경우 를 사용하여 JVM에 접속할 수 있습니다.JNIEnv*그러면 이런 문제가 생기지 않을 거예요.

    // JNIEnv* env; (initialized somewhere else)
    JavaVM* jvm;
    env->GetJavaVM(&jvm);
    // now you can store jvm somewhere

    // in the new thread:
    JNIEnv* myNewEnv;
    JavaVMAttachArgs args;
    args.version = JNI_VERSION_1_6; // choose your JNI version
    args.name = NULL; // you might want to give the java thread a name
    args.group = NULL; // you might want to assign the java thread to a ThreadGroup
    jvm->AttachCurrentThread((void**)&myNewEnv, &args);
    // And now you can use myNewEnv

Java에서 C++로의 JNI를 사용한 동기 호출에서는 JVM에 의해 "환경"이 이미 설정되었지만 임의의 C++ 스레드에서 다른 방향으로 이동하지 않았을 수 있습니다.

따라서 다음 단계를 따라야 합니다.

  • 를 사용하여 JVM 환경 컨텍스트를 입수하다GetEnv
  • 필요에 따라 콘텍스트를 부가하다AttachCurrentThread
  • 사용한 메서드를 정상이라고 부르다CallVoidMethod
  • 사용하여 분리하다DetachCurrentThread

완전한 예.주의: 과거에 블로그에 더 자세히 쓴 적이 있습니다.

JavaVM* g_vm;
env->GetJavaVM(&g_vm);

void callback(int val) {
    JNIEnv * g_env;
    // double check it's all ok
    int getEnvStat = g_vm->GetEnv((void **)&g_env, JNI_VERSION_1_6);
    if (getEnvStat == JNI_EDETACHED) {
        std::cout << "GetEnv: not attached" << std::endl;
        if (g_vm->AttachCurrentThread((void **) &g_env, NULL) != 0) {
            std::cout << "Failed to attach" << std::endl;
        }
    } else if (getEnvStat == JNI_OK) {
        //
    } else if (getEnvStat == JNI_EVERSION) {
        std::cout << "GetEnv: version not supported" << std::endl;
    }

    g_env->CallVoidMethod(g_obj, g_mid, val);

    if (g_env->ExceptionCheck()) {
        g_env->ExceptionDescribe();
    }

    g_vm->DetachCurrentThread();
}

언급URL : https://stackoverflow.com/questions/12900695/how-to-obtain-jni-interface-pointer-jnienv-for-asynchronous-calls

반응형