<span style="font-family:Comic Sans MS;font-size:14px;">class CatchThrow {
private native void doit()
throws IllegalArgumentException;
private void callback() throwsNullPointerException {
throw newNullPointerException("CatchThrow.callback");
}
public static void main(String args[]) {
CatchThrow c = new CatchThrow();
try {
c.doit();
} catch (Exception e) {
System.out.println("InJava:\n\t" + e);
}
}
static {
System.loadLibrary("CatchThrow");
}
}</span>Main方法调用本地方法doit,doit方法的实现如下:<span style="font-family:Comic Sans MS;font-size:14px;">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 == NULL) {
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 == NULL) {
/* Unable to find the exceptionclass, give up. */
return;
}
(*env)->ThrowNew(env, newExcCls,"thrown from C code");
}
}</span><span style="font-family:Comic Sans MS;font-size:14px;">void
JNU_ThrowByName(JNIEnv *env, const char *name,const char *msg)
{
jclass cls = (*env)->FindClass(env, name);
/* if cls is NULL, an exception has already been thrown */
if (cls != NULL) {
(*env)->ThrowNew(env, cls, msg);
}
/* free the local ref */
(*env)->DeleteLocalRef(env, cls);
}</span><span style="font-family:Comic Sans MS;font-size:14px;"> /* a class in the Java programming language */
public class Window {
long handle;
int length;
int width;
static native void initIDs();
static {
initIDs();
}
}
/* C codethat implements Window.initIDs */
jfieldID FID_Window_handle;
jfieldID FID_Window_length;
jfieldID FID_Window_width;
JNIEXPORT void JNICALL
Java_Window_initIDs(JNIEnv *env, jclass classWindow)
{
FID_Window_handle =
(*env)->GetFieldID(env, classWindow,"handle", "J");
if (FID_Window_handle == NULL) { /* important check. */
return; /* erroroccurred. */
}
FID_Window_length =
(*env)->GetFieldID(env, classWindow,"length", "I");
if (FID_Window_length == NULL) { /* important check. */
return; /* erroroccurred. */
}
FID_Window_width =
(*env)->GetFieldID(env, classWindow,"width", "I");
/* no checks necessary; weare about to return anyway */
}</span><span style="font-family:Comic Sans MS;font-size:14px;">public class Fraction {
// details such as constructors omitted
int over, under;
public int floor() {
return Math.floor((double)over/under);
}
}
/* Native code that callsFraction.floor. Assume method ID
MID_Fraction_floor has been initializedelsewhere. */
void f(JNIEnv*env, jobject fraction)
{
jint floor = (*env)->CallIntMethod(env, fraction,
MID_Fraction_floor);
/* important: check if an exception wasraised */
if ((*env)->ExceptionCheck(env)) {
return;
}
... /* use floor */
}</span><span style="font-family:Comic Sans MS;font-size:14px;">JNIEXPORT void JNICALL
Java_pkg_Cls_f(JNIEnv*env, jclass cls, jstring jstr)
{
const jchar *cstr =(*env)->GetStringChars(env, jstr);
if (c_str == NULL) {
return;
}
...
if (...) { /* exception occurred */
(*env)->ReleaseStringChars(env,jstr, cstr);
return;
}
...
/* normal return */
(*env)->ReleaseStringChars(env, jstr,cstr);
}
</span><span style="font-family:Comic Sans MS;font-size:14px;"> jvalue
JNU_CallMethodByName(JNIEnv*env,
jboolean *hasException,
jobject obj,
const char *name,
const char *descriptor,...)
{
va_list args;
jclass clazz;
jmethodID mid;
jvalue result;
if ((*env)->EnsureLocalCapacity(env, 2)== JNI_OK) {
clazz = (*env)->GetObjectClass(env,obj);
mid = (*env)->GetMethodID(env,clazz, name,
descriptor);
if (mid) {
const char *p = descriptor;
/* skip over argument types to findout the
return type */
while (*p != ')') p++;
/* skip ')' */
p++;
va_start(args, descriptor);
switch (*p) {
case 'V':
(*env)->CallVoidMethodV(env,obj, mid, args);
break;
case '[':
case 'L':
result.l =(*env)->CallObjectMethodV(
env,obj, mid, args);
break;
case 'Z':
result.z =(*env)->CallBooleanMethodV(
env,obj, mid, args);
break;
case 'B':
result.b =(*env)->CallByteMethodV(
env, obj, mid, args);
break;
case 'C':
result.c =(*env)->CallCharMethodV(
env,obj, mid, args);
break;
case 'S':
result.s =(*env)->CallShortMethodV(
env,obj, mid, args);
break;
case 'I':
result.i =(*env)->CallIntMethodV(
env,obj, mid, args);
break;
case 'J':
result.j =(*env)->CallLongMethodV(
env,obj, mid, args);
break;
case 'F':
result.f =(*env)->CallFloatMethodV(
env,obj, mid, args);
break;
case 'D':
result.d =(*env)->CallDoubleMethodV(
env,obj, mid, args);
break;
default:
(*env)->FatalError(env,"illegal descriptor");
}
va_end(args);
}
(*env)->DeleteLocalRef(env, clazz);
}
if (hasException) {
*hasException =(*env)->ExceptionCheck(env);
}
return result;
}</span><span style="font-family:Comic Sans MS;font-size:14px;"> JNIEXPORT void JNICALL
Java_InstanceMethodCall_nativeMethod(JNIEnv*env, jobject obj)
{
printf("In C\n");
JNU_CallMethodByName(env, NULL, obj,"callback", "()V");
}</span>
测试代码:
/**
* 异常处理
*/
public native void doExcepton() throws IllegalArgumentException;
/**
*
* @throws NullPointerException
*/
public void excepton() throws NullPointerException {
throw new NullPointerException("doExcepton.excepton");
}
/**
* 异常处理
*/
JNIEXPORT void JNICALL Java_com_example_jniandroid_service_CFunction_doExcepton(
JNIEnv * env, jobject obj) {
jthrowable exc;
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid =
(*env)->GetMethodID(env, cls, "excepton", "()V");
if (mid == NULL) {
LOGI(" MID IS NULL");
return;
}
(*env)->CallVoidMethod(env, obj, mid);
exc = (*env)->ExceptionOccurred(env);
//有异常
if (exc) {
jclass newExcCls;
(*env)->ExceptionDescribe(env);
(*env)->ExceptionClear(env);
newExcCls = (*env)->FindClass(env,"java/lang/IllegalArgumentException");
if (newExcCls == NULL) {
return;
}
(*env)->ThrowNew(env, newExcCls, "thrown from C code doExcepton");
}
}
原文地址:http://blog.csdn.net/honeybaby201314/article/details/42645311