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

Andreas :

So the documentation on GetMethodID() says this:

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

On Android, however, this doesn't seem to be the case because calling GetMethodID() with a non-existing method name always throws a fatal exception and kills the whole thread. Consider this code:

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

This results in a complete thread crash and the following output on 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 ...

Isn't this behaviour a violation of the JNI specification which clearly says that GetMethodID() should return NULL if the specified method cannot be found?

If this is really intended behaviour, is there any other way to find out from C code if a Java method exists?

Michael :

GetMethodID does return NULL in this case. However, it also throws a NoSuchMethodError exception:

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

It is an error to call most JNIEnv methods - or to try to return back to Java* - while there's a pending exception thrown by a JNI function. Note that these exceptions are not C++ exceptions, so even in C++ you can't use try/catch to catch them. And in C that would obviously not be an option anyway.

The JNIEnv provides you with the following methods to handle these exceptions:

ExceptionOccurred
ExceptionDescribe
ExceptionClear

So in this particular case where you probably don't really care about the exception, the following code would be enough to handle it:

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

These kinds of checks needs to be done after every JNI call that could throw an exception.


*Unless you catch the exeption at the Java side.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=131211&siteId=1