title: JNI native异常捕获date: 2021-07-17 23:12:43.55

updated: 2021-07-17 23:12:43.55
url: /?p=314
categories: JNI
tags:

JNI 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
46
47
48
49
50
51
52
53
54
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity3 extends AppCompatActivity {
static {
System.loadLibrary("native-lib");
}

static String name1 = "T1";

// 下面是异常处理
public static native void exception();
public static native void exception2() throws NoSuchFieldException; // NoSuchFieldException接收C++层抛上来的异常
public static native void exception3();

public static native String derryAction();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void exceptionAction(View view) {
exception(); // C++层自己做了补救措施了

// 捕获人家C++层抛上来的异常
try {
exception2();
} catch (NoSuchFieldException exception) {
exception.printStackTrace();
Log.d("Derry", "exceptionAction: 异常被我捕获了");
}

exception3();

String result = derryAction();
}

// 专门给 C++(native层) 层调用的 函数
public static void show() throws Exception {
Log.d("Derry", "show: 1111");
Log.d("Derry", "show: 1111");
Log.d("Derry", "show: 1111");
Log.d("Derry", "show: 1111");
Log.d("Derry", "show: 1111");
Log.d("Derry", "show: 1111");

throw new NullPointerException("我是Java中抛出的异常,我的show方法里面发送了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
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
68
69
70
71
72
73
74
// 异常1  【native层主动干的异常】
extern "C"
JNIEXPORT void JNICALL
Java_com_derry_as_1jni_1project_MainActivity3_exception(JNIEnv *env, jclass clazz) {
// 假设现在想操作 name999 ,没有name999就会在native层奔溃掉
jfieldID f_id = env->GetStaticFieldID(clazz, "name999", "Ljava/lang/String;");

// 奔溃后,有两种解决方案

// 方式1 补救措施

jthrowable thr = env->ExceptionOccurred(); // 监测本次执行,到底有没有异常 JNI函数里面代码有问题

if(thr) { // 非0 进去,监测到有异常
LOGD("C++层有异常 监测到了");

env->ExceptionClear(); // 此异常被清除

// 开始 补救措施
jfieldID f_id = env->GetStaticFieldID(clazz, "name1", "Ljava/lang/String;");
}


}

// 异常2 【native层主动干的异常】
extern "C"
JNIEXPORT void JNICALL
Java_com_derry_as_1jni_1project_MainActivity3_exception2(JNIEnv *env, jclass clazz) {
// 假设现在想操作 name999 ,没有name999就会在native层奔溃掉
jfieldID f_id = env->GetStaticFieldID(clazz, "name8888", "Ljava/lang/String;");

// 奔溃后,有两种解决方案

// 方式2 往Java层抛

jthrowable jthrowable = env->ExceptionOccurred(); // 监测本次执行,到底有没有异常 JNI函数里面代码有问题

if(jthrowable) { // 非0 进去,监测到有异常
LOGD("C++层有异常 监测到了");

env->ExceptionClear(); // 此异常被清除

// Throw抛一个 Java的对象 java/lang/String java/xxxxx/xxx/NullExxx
jclass clz = env->FindClass("java/lang/NoSuchFieldException");
env->ThrowNew(clz, "NoSuchFieldException 是在是找不到 name8888啊,没有办法,抛给你了");
}
}

// 异常3 【native层被动干的异常 被动 我是Java方法坑了】
extern "C"
JNIEXPORT void JNICALL
Java_com_derry_as_1jni_1project_MainActivity3_exception3(JNIEnv *env, jclass clazz) {
jmethodID showID = env->GetStaticMethodID(clazz, "show", "()V");
env->CallStaticVoidMethod(clazz, showID); // 是不是这句话奔溃的 1是 2不是 答:不是,只是他引起的而已

// ExceptionCheck 《==》 慢慢的奔溃的,相当于给了你空余时间,既然不是马上奔溃,我就可以检测

// JNI函数里面代码有问题 没有问题,给你空余时间,慢慢的奔溃的
if (env->ExceptionCheck()) {
env->ExceptionDescribe(); // 输出描述 信息
env->ExceptionClear(); // 此异常被清除 业务逻辑控制
}

// 注意实现:
/*// 奔溃后,下面的语句,照样打印
LOGI("C++层>>>>>>>>>>>>>>>>>>>>>>>>>>>>1");
LOGI("C++层>>>>>>>>>>>>>>>>>>>>>>>>>>>>2");
LOGI("C++层>>>>>>>>>>>>>>>>>>>>>>>>>>>>3");
LOGI("C++层>>>>>>>>>>>>>>>>>>>>>>>>>>>>4");
LOGI("C++层>>>>>>>>>>>>>>>>>>>>>>>>>>>>5");

env->NewStringUTF("AAAA"); // 局部引用 奔溃给磨平*/
}