多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
以下的代码中展示了如何声明一个抛出异常的Native函数。`CatchThrow`类声明了`doit`这个Native函数,并且指定了它将有可能抛出一个`IllegalArgumentException`. ~~~ public class CatchThrow { static { System.loadLibrary("CatchThrow"); } private native void doit() throws IllegalArgumentException; private void callback() throws NullPointerException { throw new NullPointerException("CatchThrow.callback"); } public static void main(String[] args){ CatchThrow c = new CatchThrow(); try { c.doit(); }catch (Exception e){ System.out.println("In Java:\n\t" + e); } } } ~~~ CatchThrow.main函数调用的Native方法doit的JNI实现如下: ~~~ /* * Class: CatchThrow * Method: doit * Signature: ()V */ JNIEXPORT void JNICALL Java_CatchThrow_doit (JNIEnv * env, jobject obj){ jthrowable exc; jclass cls = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V"); if(!mid){ return; } (*env)->CallVoidMethod(env, obj, mid); exc = (*env)->ExceptionOccurred(env); if(exc){ /* * We don't do much with the exception, except that we print a debug message for it, * clear it, and throw a new exception. */ jclass newExcCls; (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); if(!newExcCls){ /*Unable to find the exception class, give up. */ return; } (*env)->ThrowNew(env, newExcCls, "thrown from C code"); } } ~~~ 执行最终的可执行程序将会产生如下输出: ~~~ Exception in thread "main" java.lang.NullPointerException: CatchThrow.callback at CatchThrow.callback(CatchThrow.java:7) at CatchThrow.doit(Native Method) at CatchThrow.main(CatchThrow.java:12) In Java: java.lang.IllegalArgumentException: thrown from C code ~~~ 回调函数跑出了一个NullPointerException.当CallVoidMethod返回到Native函数时,Native代码通过ExceptionOccurred函数检测到这个异常。在我们的示例中,当异常被检测到的时候, Native代码通过调用ExceptionDescribe输出了一段描述性信息,然后调用ExceptionClear清除了异常信息,最后抛出了一个IllegalArgumentException. JNI代码引起的异常(例如,通过ThrowNew抛出的异常)不会立即打断Native代码的执行流程。这与Java程序语言中异常处理逻辑是不同的。在Java语言中,如果有异常被抛出,虚拟机就会自动的把控制流程转向匹配异常类型的最近层次的try/catch语句声明,然后虚拟机清空异常并继续执行异常处理逻辑。相比之下,JNI程序员在异常出现的时候必须显示实现代码的控制流程。