第六章之刻意练习
经过第六章的学习,基本了解JNI的异常处理了,现在我们来刻意练习一下
practice 1, 在native层获取Java异常并将异常抛出给Java层
我们需要在native方法中实现除法,除法的除数是不能为零的,所以如果Java在调用native方法的除法时,穿进去的第二个参数为0的话,我们就要抛出一个 java.lang.ArithmeticExpection:/by zero的异常到Java空间中,然后再Java空间中处理这个异常。Java侧的工作就比较简单了,我们只要在Java侧获取除法需要的两个double值,然后调用native层的方法就可以了。OK,下面我们开始编程吧,有时间还是建议先自己写一下代码。
下面是我写的代码
Java侧代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import java.util.Scanner; import java.lang.ArithmeticException; class Divition { private native double div(double a, double b) throws ArithmeticException; public static void main(String[] args) { Scanner sc = new Scanner(System.in); Divition di = new Divition(); System.out.print("Enter the first double number: "); double a = sc.nextDouble(); System.out.print("Enter the second double number: "); double b = sc.nextDouble(); double result = 0.0; try { result = di.div(a, b); System.out.println(a + " / " + b + " = " + result); } catch(ArithmeticException e) { e.printStackTrace(); } } static { System.loadLibrary("Divition"); } } |
代码意图明显,就是获取输入,然后再try catch中调用方法。下面看看native层代码怎么实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#include <jni.h> #include <stdio.h> JNIEXPORT jdouble JNICALL native_div(JNIEnv * env, jobject obj, jdouble a, jdouble b) { if(b == 0) { jclass clazz = (*env)->FindClass(env, "java/lang/ArithmeticException"); if(clazz != NULL) { (*env)->ThrowNew(env, clazz, "/ by zero"); } (*env)->DeleteLocalRef(env, clazz); return NULL; } return (a / b); } static const JNINativeMethod gMethods[] = { {"div", "(DD)D", native_div} }; static jclass myClass; static const char * ClassName = "Divition"; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM * vm, void * reversed) { JNIEnv * env = NULL; if((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) { printf("GetEnv return error.\n"); return -1; } myClass = (*env)->FindClass(env, ClassName); if(myClass == NULL) { printf("FindClass return error.\n"); return -1; } if((*env)->RegisterNatives(env, myClass, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0) { printf("RegisterNatives return error\n"); return -1; } return JNI_VERSION_1_6; } |
上面的处理也是比较简单的,在函数开始的时候就直接判断除数是否为0,如果为零就找到对应的异常类,然后调用ThrowNew,将异常抛出到Java处。
接下来直接编译运行就好了。这里主要联系下怎么获取Java中的异常类,然后将其抛出到Java层。
practice 2,在native中调用Java的方法,并在native层中处理异常
这里做同样的练习好了,现在我们在Java层中编写除法的代码,然后我们在native层获取输入,然后调用Java层的除法,然后判断是否有异常抛出,如果与的话就处理异常,否则打印结果。
下面是我写的代码
Java侧代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import java.lang.ArithmeticException; class Divition2 { private native void callDiv(); private double div(double a, double b) throws ArithmeticException { if(b == 0) { throw new ArithmeticException("/ by zero"); } else { return (a / b); } } public static void main(String[] args) { Divition2 di = new Divition2(); di.callDiv(); } static { System.loadLibrary("Divition2"); } } |
这里不多解释了,代码简单,看一下就懂
ntive侧代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
#include <jni.h> #include <stdio.h> JNIEXPORT void JNICALL native_callDiv(JNIEnv * env, jobject obj) { jdouble a = 0.0; jdouble b = 0.0; jdouble result = 0.0; jthrowable exc; jclass clazz; jmethodID mid; printf("Enter the first double number: "); scanf("%lf", &a); printf("Enter the second double number: "); scanf("%lf", &b); clazz = (*env)->GetObjectClass(env, obj); mid = (*env)->GetMethodID(env, clazz, "div", "(DD)D"); if(mid == NULL) { printf("GetMethodID return error\n"); return; } result = (*env)->CallDoubleMethod(env, obj, mid, a, b); exc = (*env)->ExceptionOccurred(env); if(exc) { // 有异常出现 (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } else { printf("%lf / %lf = %lf\n", a, b, result); } return; } static const JNINativeMethod gMethods[] = { {"callDiv", "()V", native_callDiv} }; static jclass myClass; static const char * ClassName = "Divition2"; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM * vm, void * reversed) { JNIEnv * env = NULL; if((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) { printf("GetEnv return error.\n"); return -1; } myClass = (*env)->FindClass(env, ClassName); if(myClass == NULL) { printf("FindClass return error.\n"); return -1; } if((*env)->RegisterNatives(env, myClass, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0) { printf("RegisterNatives return error\n"); return -1; } return JNI_VERSION_1_6; } |
** 此文为博主原创文章,转载请注明出处 **