Issue
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?
Solution
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.
Answered By - Michael
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.