Почему GetMethodID () не возвращает NULL для несуществующего метода? - PullRequest
0 голосов
/ 26 января 2019

Итак, документация по GetMethodID () гласит:

Возвращает идентификатор метода или 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, которая четко говоритчто GetMethodID() должно возвращать NULL, если указанный метод не может быть найден?

Если это действительно предполагаемое поведение, есть ли другой способ узнать из кода C, существует ли метод Java?

1 Ответ

0 голосов
/ 27 января 2019

GetMethodID возвращает в этом случае NULL.Однако также выдается исключение NoSuchMethodError:

THROWS:
NoSuchMethodError: если указанный метод не может быть найден.

Ошибка вызывать большинство JNIEnv методов - или пытаться вернуться обратно на Java * - пока существует ожидающее исключение, выданное функцией JNI.Обратите внимание, что эти исключения не являются исключениями C ++, поэтому даже в C ++ вы не можете использовать try / catch для их перехвата.И в C это, очевидно, не будет вариантом в любом случае.

JNIEnv предоставляет вам следующие методы для обработки этих исключений:

ExceptionOccurred
ExceptionDescribe
ExceptionClear

Так что в данном конкретном случае, когда вы, вероятно,на самом деле не волнует исключение, для его обработки будет достаточно следующего кода:

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

Такие проверки необходимо выполнять после каждого вызова JNI, который может вызвать исключение.


* Если вы не уловили исключение на стороне Java.

...