A Programmer

# 第六章之刻意练习

经过第六章的学习，基本了解JNI的异常处理了，现在我们来刻意练习一下

#### practice 1， 在native层获取Java异常并将异常抛出给Java层

###### 下面是我写的代码

Java侧代码

```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 {
}
}
```

```#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;
}
```

接下来直接编译运行就好了。这里主要联系下怎么获取Java中的异常类，然后将其抛出到Java层。

#### practice 2，在native中调用Java的方法，并在native层中处理异常

###### 下面是我写的代码

Java侧代码：

```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 {
}
}
```

ntive侧代码：

```#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;
}
```

** 此文为博主原创文章，转载请注明出处 **