JNI异常处理

    xiaoxiao2021-03-25  144

    在java中,我们经常需要处理异常。然而,在C本地方法中,我们同样需要处理异常。

    下面我们来看下一般的处理:

    class 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); } } static { System.loadLibrary("CatchThrow"); } }

     

    当本地方法调用Callback方法抛出一个异常后,(*env)->ExceptionOccurred(env);方法将返回true。然后本地方法在抛出一个本地异常,通过(*env)->ThrowNew()抛出异常。所以,本地方法最终也是调用java方法来抛出异常的。

    打印结果: java.lang.NullPointerException: at CatchThrow.callback(CatchThrow.java) at CatchThrow.doit(Native Method) at CatchThrow.main(CatchThrow.java) In Java: java.lang.IllegalArgumentException: thrown from C code 既然这样,我们可以专门提供一个工具方法,用于抛出异常。

    关于函数名称:JNU表示JNI Utilities(JNI工具)。

    下面提供一个更全面的异常工具方法:

    jvalue JNU_CallMethodByName(JNIEnv *env, jboolean *hasException, jobject obj, const char *name, const char *descriptor, ...) { va_list args; jclass clazz; jmethodID mid; jni.book Page 79 Thursday, February 21, 2002 4:36 PM 6.2.3 Exceptions in Utility Functions EXCEPTIONS 80 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 find out 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( jni.book Page 80 Thursday, February 21, 2002 4:36 PM EXCEPTIONS Exceptions in Utility Functions 6.2.3 81 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; }

    调用方法:

    JNIEXPORT void JNICALL Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj) { printf("In C\n"); JNU_CallMethodByName(env, NULL, obj, "callback", "()V"); }

    转载请注明原文地址: https://ju.6miu.com/read-3080.html

    最新回复(0)