JNI:调用 GetStaticMethodID 失败

fre*_*ith 5 c++ java java-native-interface android

我正在编写一些代码来获取生成的线程以从 C++ 调用静态 Java 方法。

如果放置在来自 Java 的本机调用中,则调用该方法的位可以正常工作,但不能来自具有附加 JNIEnv 的线程。

我已经设置了一个 JavaVM* 如下:

jint JNI_OnLoad(JavaVM* jvm, void* reserved)
{
    LOGI("Setting Java Virtual Machine");

    ThreadJNIEnvironment::javaVM = jvm;

    return JNI_VERSION_1_6;
}
Run Code Online (Sandbox Code Playgroud)

这确实被调用了。

然后我生成另一个线程,并从该线程执行以下操作:

JNIEnv* env;
jint ret = ThreadJNIEnvironment::javaVM->AttachCurrentThread(&env, NULL);

LOGI("AttachCurrentThread returned %d", ret);

jclass interfaceClass = env->FindClass("com/ecmsys/mcb/model/McbInterface");
jmethodID testMethod = env->GetStaticMethodID(interfaceClass, "Test", "()V");
env->CallStaticVoidMethod(interfaceClass, testMethod);
Run Code Online (Sandbox Code Playgroud)

AttachCurrentThread 返回 0。

GetStaticMethod 会因以下错误而崩溃:

Fatal signal 11 (SIGSEGV) at 0x0000002c (code=1).....
Run Code Online (Sandbox Code Playgroud)

我只是看不出我做了什么来扰乱它......哦等等......你不能在没有做一些设置的情况下从一个衍生的线程访问 Java 应用程序类......

jint JNI_OnLoad(JavaVM* jvm, void* reserved)
{
    LOGI("Setting Java Virtual Machine");
    ThreadJNIEnvironment::javaVM = jvm;

    JNIEnv* env;


    jvm->AttachCurrentThread(&env, NULL);
    jclass mcbInterface = env->FindClass("com/ecmsys/mcb/model/McbInterface");
    ThreadJNIEnvironment::interfaceClass = env->NewGlobalRef(mcbInterface);

    return JNI_VERSION_1_6;
} 
Run Code Online (Sandbox Code Playgroud)

然后这样做:

JNIEnv* env;
jint ret = ThreadJNIEnvironment::javaVM->AttachCurrentThread(&env, NULL);

LOGI("AttachCurrentThread retured %d", ret);

if(ThreadJNIEnvironment::interfaceClass)
{
    jmethodID testMethod = env-->GetStaticMethodID(static_cast<jclass>ThreadJNIEnvironment::interfaceClass), "Test", "()V");
    env->CallStaticVoidMethod(static_cast<jclass>(ThreadJNIEnvironment::interfaceClass), testMethod);
}


ThreadJNIEnvironment::javaVM->DetachCurrentThread();
Run Code Online (Sandbox Code Playgroud)

你生活和学习!

tec*_*age 4

查找interfaceClass( env->ExceptionCheck()) 后检查是否有异常,或者简单地检查它是否为非 NULL。最有可能的是类查找失败。

  • 您还可以缓存方法 ID(您不需要为此提供引用),并且应该为该类使用弱全局引用。您需要该引用,因为您所拥有的类引用超出了单个 JNI 调用的范围(您获得的初始引用是本地引用)。 (3认同)