Мой код запускается на Java, вызывает C ++, который затем снова вызывает Java для таких вещей, как поиск, получение и установка значений полей.
В случае, если кто-то, ищущий подход C ++, найдет эту страницу, я запишу следующее:
То, что я сейчас делаю, это обёртываю тела моего метода JNI блоком C ++ try / catch,
JNIEXPORT void JNICALL Java_com_pany_jni_JNIClass_something(JNIEnv* env, jobject self)
{
try
{
... do JNI stuff
// return something; if not void.
}
catch (PendingException e) // (Should be &e perhaps?)
{
/* any necessary clean-up */
}
}
где PendingException объявляется тривиально:
class PendingException {};
и я вызываю следующий метод после вызова любого JNI из C ++, поэтому, если состояние исключения Java указывает на ошибку, я немедленно освобождаюсь от обязательств и позволяю обычной обработке исключений Java добавить строку (метод Native) в стек трассировки, давая C ++ возможность очистить при разматывании:
PendingException PENDING_JNI_EXCEPTION;
void throwIfPendingException(JNIEnv* env)
{
if (env->ExceptionCheck()) {
throw PENDING_JNI_EXCEPTION;
}
}
Моя трассировка стека Java выглядит следующим образом при неудачном вызове env-> GetFieldId ():
java.lang.NoSuchFieldError: no field with name='opaque' signature='J' in class Lcom/pany/jni/JniClass;
at com.pany.jni.JniClass.construct(Native Method)
at com.pany.jni.JniClass.doThing(JniClass.java:169)
at com.pany.jni.JniClass.access$1(JniClass.java:151)
at com.pany.jni.JniClass$2.onClick(JniClass.java:129)
at android.view.View.performClick(View.java:4084)
и очень похоже, если я вызову метод Java, который выдает:
java.lang.RuntimeException: YouSuck
at com.pany.jni.JniClass.fail(JniClass.java:35)
at com.pany.jni.JniClass.getVersion(Native Method)
at com.pany.jni.JniClass.doThing(JniClass.java:172)
Я не могу говорить о переносе исключения Java в другое исключение Java из C ++, что, как мне кажется, является частью вашего вопроса - я не нашел в этом необходимости - но если бы я это сделал, я бы тоже сделайте это с помощью обертки уровня Java вокруг нативных методов или просто расширьте мои методы генерирования исключений, чтобы взять jthrowable и заменить вызов env-> ThrowNew () чем-то безобразным: к сожалению, Sun не предоставила версию ThrowNew это заняло jrowrowable.
void impendNewJniException(JNIEnv* env, const char *classNameNotSignature, const char *message)
{
jclass jClass = env->FindClass(classNameNotSignature);
throwIfPendingException(env);
env->ThrowNew(jClass, message);
}
void throwNewJniException(JNIEnv* env, const char* classNameNotSignature, const char* message)
{
impendNewJniException(env, classNameNotSignature, message);
throwIfPendingException(env);
}
Я бы не стал рассматривать кеширование (исключение) ссылок на конструкторы классов, потому что исключения не должны быть обычным механизмом потока управления, поэтому не должно иметь значения, если они медленные. Я полагаю, что поиск в любом случае не очень медленный, так как, по-видимому, Java для этой вещи выполняет собственное кэширование.