2

以下是java代码,旁边是c代码:

package Package;

public class CatchThrow {

private native void doit() throws IllegalArgumentException;

private void callBack() throws NullPointerException {
    System.out.println("In call-back !");
    throw new NullPointerException("CatchThrow.callBack");
}

public static void main(String args[]) {
    CatchThrow c = new CatchThrow();
    try {
        c.doit();
    } catch(Exception exc) {
        System.out.println("\nIn Java : \n\t" + exc);
    }
}

 static {
     System.loadLibrary("CatchThrow");
 }
}

C代码:

#include "stdio.h"
#include "Package_CatchThrow.h"

void Java_Package_CatchThrow_doit
   (JNIEnv *env, jobject obj) {
  jthrowable exc;
  jclass cls = (*env)->GetObjectClass(env,obj);
  jmethodID mid = (*env)->GetMethodID(env,cls,"callBack","()V");
  if(mid == NULL) {
    return;
  }
  (*env)->CallVoidMethod(env,obj,mid); // call the java method that throws NullPointerException
  printf("After the call to Call-Back !");
  exc = (*env)->ExceptionOccurred(env);
  if(exc) {
    jclass newExcCls;
    printf("\n");
    //(*env)->ExceptionDescribe(env);  ----> NOTE THE COMMENTED STATEMENT
    //(*env)->ExceptionClear(env);  -----> NOTE THE COMMENTED STATEMENT
    newExcCls = (*env)->FindClass(env,"java/lang/IllegalArgumentException");
    if(newExcCls == NULL) {
        return;
    }
    (*env)->ThrowNew(env,newExcCls,"thrown from c code");
  }

}

当我构建并运行上述程序时,我得到以下输出:

In call-back !
After the call to Call-Back !

In Java :
    java.lang.IllegalArgumentException: thrown from c code

从输出: C 代码调用 java 函数callBack。那里打印了第一条语句。在调用返回调用旁边的语句后,即After the call to Call-Back !打印出来。但是throw new NullPointerException("CatchThrow.callBack");java 函数callBack中的语句发生了什么?为什么它不打印异常?

但是如果我从陈述中删除评论

(*env)->ExceptionDescribe(env);
(*env)->ExceptionClear(env);

评论说,我得到了所需的输出:

In call-back !
After the call to Call-Back !
Exception in thread "main" java.lang.NullPointerException: CatchThrow.callBack
    at Package.CatchThrow.callBack(CatchThrow.java:14)
    at Package.CatchThrow.doit(Native Method)
    at Package.CatchThrow.main(CatchThrow.java:20)

In Java :
    java.lang.IllegalArgumentException: thrown from c code

这是为什么 ?

这两个语句的作用是什么?为什么在没有这两条语句的情况下不打印异常?

4

2 回答 2

2

new NullPointerException("CatchThrow.callBack");从不接触 Java 运行时,并且完全在 JNI 空间中处理。

因此,除非您调用 JNI ExceptionDescribe 函数,否则不会打印任何异常详细信息:

(*env)->ExceptionDescribe(env); 

您不能从 JNI 返回多个异常,因此返回到 Java 运行时中的 try/catch 块的唯一异常信息是您稍后创建的异常信息:

(*env)->ThrowNew(env,newExcCls,"thrown from c code"); 

通过 JNI 引发的未决异常(例如,通过调用 ThrowNew)不会立即中断本机方法的执行。这与 Java 编程语言中异常的行为方式不同。当 Java 编程语言中抛出异常时,虚拟机会自动将控制流转移到最近的与异常类型匹配的封闭 try/catch 语句。然后虚拟机清除挂起的异常并执行异常处理程序。相反,JNI 程序员必须在异常发生后显式地实现控制流。

来自关于异常的 JNI 文档

于 2012-05-09T08:11:48.553 回答
0

根据文件ExceptionDescribe

将堆栈的异常和回溯打印到系统错误报告通道,例如stderr. 这是为调试提供的便利例程。

ExceptionClear

清除当前抛出的任何异常。如果当前没有抛出异常,则此例程无效。

这通常不是你想要的。我建议以IllegalArgumentExceptionNPE 作为原因进行创建。在 Java 中,你会这样写:

throw new IllegalArgumentException( "thrown from c code", exc );

这样,内部和外部异常(包括堆栈跟踪)在 Java 级别可用,您可以在其中检查它们。

于 2012-05-09T08:11:37.783 回答