Java方法在抛出异常时返回JNI调用方的内容是什么?

时间:2013-10-01 15:42:53

标签: java exception java-native-interface

说我有以下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没有“正常”范围。

我现在正在尝试这个,但我主要是问这个问题,看看是否有某种强制行为。

2 个答案:

答案 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