说我有以下Java代码:
public class Test {
public static int foo() {
throw new RuntimeException();
}
}
以常规方式加载本机库。本机库注册并缓存JVM或其他任何东西,然后,稍后执行此函数:
JNIEnv* sEnv; // initialised somewhere properly
void throwMeARiver() {
jclass c = sEnv->FindClass("Test");
jmethodID m = sEnv->GetStaticMethodID(c, "foo", "()I");
jint i = sEnv->CallStaticIntMethod(c, m);
printf("Got %d\n", (int)i);
}
显然sEnv-> CheckException()现在将返回JNI_TRUE,但是本机函数会打印出什么?在Java中,抛出异常会使JVM停止执行它所在的方法,直到找到合适的处理程序,因此foo()的返回值是未定义的。我也是未定义的吗?
我找不到任何规格或其他任何说法,所以大概是i / is / undefined。与大多数JNI函数不同,在这种情况下,CallStaticIntMethod没有“正常”范围。
我现在正在尝试这个,但我主要是问这个问题,看看是否有某种强制行为。
答案 0 :(得分:2)
虽然将定义变量i,但其值未确定。在这种情况下,最有可能的是,该值将为0,但前提是JVM在其实现中初始化了该值。否则,它将等于存储器中其位置的数据。
由原生函数的实现者来正确检查CallXXXMethod()
后env->CheckException()
,env->ExceptionOccurred()
和env->ExceptionDescribe()
之后的异常。最后,调用env->ClearException()
删除异常。
答案 1 :(得分:-1)
不,JNI CheckException()不等同于Java try ... catch,因此你的新 RuntimeException()
将会进一步传播,可能根本不会被捕获。
感谢@EJP纠正我:实际上,来自Java的任何Throwable都被C / C ++调用者拦截。从我在Android上的测试中,返回的值是在某些不可预测的内存位置(堆栈?)中发生的任何事情。
有关JNI和例外的更多讨论,请参阅How to catch JNI/Java Exception。