为什么不在不存在的方法上使用 GetMethodID() return NULL?

Why doesn't GetMethodID() return NULL on non-existing method?

所以 GetMethodID() 上的文档是这样说的:

Returns a method ID, or NULL if the specified method cannot be found.

然而,在 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 规范,该规范明确规定如果找不到指定的方法,GetMethodID() 应该 return NULL

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

GetMethodID 在这种情况下 return NULL。但是,它还会抛出 NoSuchMethodError 异常:

THROWS:
NoSuchMethodError: if the specified method cannot be found.

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

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

ExceptionOccurred
ExceptionDescribe
ExceptionClear

因此在这种您可能并不真正关心异常的特殊情况下,以下代码足以处理它:

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

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


*除非你在Java这边捕获了异常。