JNI异常处理


在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");
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值