|
|
Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
When an exception is thrown in Java, the Java Virtual Machine automatically looks for the nearest enclosing exception handler and unwinds the stack if necessary. This style of exception handling frees the programmer from caring about and handling unusual error cases at every operation in the program. Instead, the Java Virtual Machine propagates the error conditions automatically to a location (the
catchclause in Java) that can handle the same class of error conditions in a centralized way.While other languages such as C++ support a similar notion of exception handling, there is no uniform and general way to throw and catch exceptions in native languages. The JNI therefore requires you to check for possible exceptions after calling JNI functions. The JNI also provides functions that allow your native methods to throw Java exceptions. These exceptions can then be handled either by other parts of your native code or by the Java Virtual Machine. After the native code catches and handles an exception, it can either clear the pending exception so that the computation may continue, or it can throw another exception for an outer exception handler.
Many JNI functions may cause an exception to be thrown. For example, the
GetFieldIDfunction described in the previous section throws aNoSuchFieldErrorif the specified field does not exist. To simplify error checking, most JNI functions use a combination of error codes and Java exceptions to report error conditions. For example, you may check if thejfieldIDreturned fromGetFieldIDis zero (0) instead of calling the JNI functionExceptionOccurred. When the result ofGetFieldIDis not zero (0), you are guaranteed that there is no pending exception.The remainder of this section illustrates how to catch and throw exceptions in native code. The example code is in
CatchThrow.java.
The
CatchThrow.mainmethod calls the native method. The native method, defined inCatchThrow.c, first invokes the Java methodCatchThrow.callback, as follows:... jclass cls = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V"); jthrowable exc; if (mid == 0) { return; } (*env)->CallVoidMethod(env, obj, mid); ...
Note: BecauseCallVoidMethodthrows aNullPointerException, the native code can detect this exception afterCallVoidMethodreturns by calling the methodExceptionOccurred:... exc = (*env)->ExceptionOccurred(env); if (exc) { ...You can see that it is a simple matter to catch and handle an exception. In our example, we do not do much about the exception in
CatchThrow.cexcept to use the methodExceptionDescribeto output a debugging message. The native method then throws anIllegalArgumentException. It is thisIllegalArgumentExceptionthat the Java code which invoked the native method will see.... (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); if (newExcCls == 0) { /* Unable to find the new exception class, give up. */ return; } (*env)->ThrowNew(env, newExcCls, "thrown from C code"); ...The
ThrowNewfunction constructs an exception object from the given exception class and message string and posts the exception in the current thread.
Note: It is extremely important to check, handle, and clear the pending exception before calling subsequent JNI functions. Calling arbitrary JNI functions with a pending exception may lead to unexpected results. You can safely call only a small number of JNI functions when there is a pending exception. These functions areExceptionOccurred,ExceptionDescribe, andExceptionClear.
|
|
Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
Copyright 1995-2004 Sun Microsystems, Inc. All rights reserved.