为什么GetMethodID()在不存在的方法上不返回NULL?

时间:2019-01-26 14:18:14

标签: java android c android-ndk java-native-interface

因此GetMethodID()上的文档说:

  

返回方法ID,如果找不到指定的方法,则返回NULL。

但是,在Android上似乎并非如此,因为使用不存在的方法名称调用GetMethodID()总是会引发致命异常并杀死整个线程。考虑以下代码:

jmethodID id = (*env)->GetMethodID(env, mActivityClass, "iDontExist", "()V");

这将导致完整的线程崩溃,并在Logcat上显示以下输出:

01-26 15:11:30.210  6403  6507 F art     : art/runtime/thread.cc:1657] No pending exception expected: java.lang.NoSuchMethodError: no non-static method "Lcom/example/test/TestActivity;.iDontExist()V"
01-26 15:11:30.210  6403  6507 F art     : art/runtime/thread.cc:1657]   at void com.example.test.TestActivity.nativeRunTest(java.lang.String, java.lang.String) ((null):-2)
01-26 15:11:30.210  6403  6507 F art     : art/runtime/thread.cc:1657]   at void com.example.test.TestMain.run() ((null):-1)
01-26 15:11:30.210  6403  6507 F art     : art/runtime/thread.cc:1657]   at void java.lang.Thread.run() (Thread.java:761)
01-26 15:11:30.210  6403  6507 F art     : art/runtime/thread.cc:1657]
01-26 15:11:30.253  6403  6507 F art     : art/runtime/runtime.cc:422] Runtime aborting...
01-26 15:11:30.253  6403  6507 F art     : art/runtime/runtime.cc:422] Aborting thread:
01-26 15:11:30.253  6403  6507 F art     : art/runtime/runtime.cc:422] "TestThread" prio=5 tid=14 Runnable
... lots of lines indicating a crash follow ...

此行为是否违反JNI规范,JNI规范明确指出如果找不到指定的方法,GetMethodID()应该返回NULL

如果这确实是预期的行为,是否还有其他方法可以从C代码中找出Java方法是否存在?

1 个答案:

答案 0 :(得分:1)

在这种情况下,

GetMethodID 返回NULL。但是,它还会引发NoSuchMethodError异常:

  

投掷
  NoSuchMethodError:如果找不到指定的方法。

在JNI函数抛出未决异常时,调用most JNIEnv methods-或尝试返回Java * 是错误的。请注意,这些异常不是C ++异常,因此即使在C ++中,也无法使用try / catch来捕获它们。而且在C语言中,这显然不是一个选择。

JNIEnv为您提供了以下方法来处理这些异常:

ExceptionOccurred
ExceptionDescribe
ExceptionClear

因此,在这种情况下,您可能并不十分在意该异常,因此以下代码足以处理该异常:

if ((*env)->ExceptionCheck(env)) {
    (*env)->ExceptionClear(env);
}

在每次可能引发异常的JNI调用之后,都需要进行这类检查。


* 除非您在Java方面遇到了麻烦。