JNI学习笔记——(四)kotlin声明并调用Native函数、JNI异常

注:编码工具是Android Studio。

目录

kotlin声明并调用Native函数

JNI异常

案例一

案例二

案例三


kotlin声明并调用Native函数

KotlinJniActivity代码

package com.android.jni.study.day22

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.android.jni.study.R
import kotlinx.android.synthetic.main.activity_kotlin_jni.*

class KotlinJniActivity : AppCompatActivity() {

    // external 类似于 Java 的 native
    private external fun sort(intArray: IntArray)

    // 类似于 Java 的 static{}
    companion object {
        init {
            System.loadLibrary("native-lib")
        }
    }
    private val TAG = "KOTLIN_JNI_DEMO"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_kotlin_jni)
        tv.setOnClickListener {
            val intArray = intArrayOf(3, -1, 7, 99, 1, -5, 8, 19, 12, 17, 5, 4)
            Log.e(TAG, "before sort:${intArray.joinToString()}")
            sort(intArray)
            Log.e(TAG, "after sort:${intArray.joinToString()}")
        }
    }
}

native代码

#include <jni.h>
#include <android/log.h>
#include <iostream>

#define TAG "KOTLIN_JNI_DEMO"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)

int compare(const int *n1, const int *n2) {
    return *n1 - *n2;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_day22_KotlinJniActivity_sort(JNIEnv *env, jobject thiz,
                                                        jintArray int_array) {
    jint *array = env->GetIntArrayElements(int_array, 0);
    jsize length = env->GetArrayLength(int_array);
    qsort(array, length, sizeof(int),
          reinterpret_cast<int (*)(const void *, const void *)>(compare));
    env->ReleaseIntArrayElements(int_array, array, 0);
}

点击click输出

2021-12-23 20:57:18.314 25729-25729/com.wcc.jni.study E/KOTLIN_JNI_DEMO: before sort:3, -1, 7, 99, 1, -5, 8, 19, 12, 17, 5, 4
2021-12-23 20:57:18.316 25729-25729/com.wcc.jni.study E/KOTLIN_JNI_DEMO: after sort:-5, -1, 1, 3, 4, 5, 7, 8, 12, 17, 19, 99

JNI异常

案例一

KotlinJniActivity代码

package com.android.jni.study.day22

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.android.jni.study.R
import kotlinx.android.synthetic.main.activity_kotlin_jni.*

class KotlinJniActivity : AppCompatActivity() {

    // external 类似于 Java 的 native
    private external fun exception1()
    private var name: String = "default"

    // 类似于 Java 的 static{}
    companion object {
        init {
            System.loadLibrary("native-lib")
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_kotlin_jni)
        tv.setOnClickListener {
            exception1()
        }
    }
}

native代码

#include <jni.h>
#include <android/log.h>
#include <iostream>

#define TAG "KOTLIN_JNI_DEMO"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)

extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_day22_KotlinJniActivity_exception1(JNIEnv *env, jobject thiz) {
    jclass jclz = env->GetObjectClass(thiz);
    jfieldID field_id = env->GetFieldID(jclz, "nameNotExist", "Ljava/lang/String;");
    jthrowable pJthrowable = env->ExceptionOccurred();
    if(pJthrowable != 0) {
        LOGE("有异常产生了...");
    }
}

点击click输出:

2021-12-23 21:07:45.566 25825-25825/com.wcc.jni.study E/KOTLIN_JNI_DEMO: 有异常产生了...
2021-12-23 21:07:45.568 25825-25825/com.wcc.jni.study E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.wcc.jni.study, PID: 25825
    java.lang.NoSuchFieldError: no "Ljava/lang/String;" field "nameNotExist" in class "Lcom/android/jni/study/day22/KotlinJniActivity;" or its superclasses
        at com.android.jni.study.day22.KotlinJniActivity.exception1(Native Method)
        at com.android.jni.study.day22.KotlinJniActivity.access$exception1(KotlinJniActivity.kt:9)
        at com.android.jni.study.day22.KotlinJniActivity$onCreate$1.onClick(KotlinJniActivity.kt:29)
        at android.view.View.performClick(View.java:7140)
        at android.view.View.performClickInternal(View.java:7117)
        at android.view.View.access$3500(View.java:801)
        at android.view.View$PerformClick.run(View.java:27351)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
    
    
    --------- beginning of system
2021-12-23 21:07:45.639 1937-2059/system_process E/InputDispatcher: channel '261409 com.wcc.jni.study/com.android.jni.study.day22.KotlinJniActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
2021-12-23 21:07:48.692 1937-2780/system_process E/TaskPersister: File error accessing recents directory (directory doesn't exist?).

        其实nameNotExist在IDE里会报红,为了演示异常特意制造异常。

        补救措施

native代码

#include <jni.h>
#include <android/log.h>
#include <iostream>

#define TAG "KOTLIN_JNI_DEMO"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)

extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_day22_KotlinJniActivity_exception1(JNIEnv *env, jobject thiz) {
    jclass jclz = env->GetObjectClass(thiz);
    jfieldID field_id = env->GetFieldID(jclz, "nameNotExist", "Ljava/lang/String;");
    jthrowable pJthrowable = env->ExceptionOccurred();
    if(pJthrowable != 0) {
        LOGE("有异常产生了...");
        env->ExceptionClear();// 清除异常
        // 做补救
        field_id = env->GetFieldID(jclz, "name", "Ljava/lang/String;");
        jstring jstr = static_cast<jstring>(env->GetObjectField(thiz, field_id));
        const char *str = env->GetStringUTFChars(jstr, 0);
        LOGE("name is %s", str);
    }
}

点击click输出

2021-12-23 21:15:58.968 26089-26089/com.wcc.jni.study E/KOTLIN_JNI_DEMO: 有异常产生了...
2021-12-23 21:15:58.968 26089-26089/com.wcc.jni.study E/KOTLIN_JNI_DEMO: name is default

        可以从输出看出异常被清除了。

案例二

JniActivity代码

package com.android.jni.study;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class JniActivity extends AppCompatActivity {

    // 加载本地库
    static {
        System.loadLibrary("native-lib");
    }

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

    public static native void exception2() throws NoSuchFieldException;

    public void click(View view) {
        try {
            exception2();
        } catch (Exception e) {
            Log.e("JNI", e.getMessage());
        }
    }
}

native代码

#include <jni.h>
#include <android/log.h>
#include <iostream>

#define TAG "JNI"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)

extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_JniActivity_exception2(JNIEnv *env, jclass clazz) {
    jfieldID f_id = env->GetStaticFieldID(clazz, "nameNotExist", "Ljava/lang/String;");
    jthrowable pJthrowable = env->ExceptionOccurred();
    if (pJthrowable) {
        LOGE("有异常产生了...");
        env->ExceptionClear();// 清除异常
        jclass jclz = env->FindClass("java/lang/NoSuchFieldException");
        env->ThrowNew(jclz, "没有nameNotExist字段...");// 向Java层抛出一个新异常
    }
}

点击click输出

2021-12-23 21:27:33.350 26394-26394/com.wcc.jni.study E/JNI: 有异常产生了...
2021-12-23 21:27:33.351 26394-26394/com.wcc.jni.study E/JNI: 没有nameNotExist字段...

案例三

JniActivity代码

package com.android.jni.study;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;

public class JniActivity extends AppCompatActivity {

    // 加载本地库
    static {
        System.loadLibrary("native-lib");
    }

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

    private native void exception3();

    private void show() throws Exception {
        throw new NullPointerException("空指针异常...");
    }

    public void click(View view) {
        exception3();
    }
}

native代码

#include <jni.h>
#include <android/log.h>
#include <iostream>

#define TAG "JNI"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)

extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_JniActivity_exception3(JNIEnv *env, jobject thiz) {
    jclass jclz = env->GetObjectClass(thiz);
    jmethodID m_id = env->GetMethodID(jclz, "show", "()V");
    env->CallVoidMethod(thiz, m_id);
    // 如果检查到异常
    if (env->ExceptionCheck()) {
        env->ExceptionDescribe();// 打印异常信息
        env->ExceptionClear();// 清除异常
    }
}

点击click输出

2021-12-23 21:34:28.475 26494-26494/com.wcc.jni.study W/System.err: java.lang.NullPointerException: 空指针异常...
2021-12-23 21:34:28.475 26494-26494/com.wcc.jni.study W/System.err:     at com.android.jni.study.JniActivity.show(JniActivity.java:32)
2021-12-23 21:34:28.475 26494-26494/com.wcc.jni.study W/System.err:     at com.android.jni.study.JniActivity.exception3(Native Method)
2021-12-23 21:34:28.476 26494-26494/com.wcc.jni.study W/System.err:     at com.android.jni.study.JniActivity.click(JniActivity.java:36)
2021-12-23 21:34:28.476 26494-26494/com.wcc.jni.study W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2021-12-23 21:34:28.476 26494-26494/com.wcc.jni.study W/System.err:     at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409)
2021-12-23 21:34:28.476 26494-26494/com.wcc.jni.study W/System.err:     at android.view.View.performClick(View.java:7140)
2021-12-23 21:34:28.476 26494-26494/com.wcc.jni.study W/System.err:     at android.view.View.performClickInternal(View.java:7117)
2021-12-23 21:34:28.476 26494-26494/com.wcc.jni.study W/System.err:     at android.view.View.access$3500(View.java:801)
2021-12-23 21:34:28.476 26494-26494/com.wcc.jni.study W/System.err:     at android.view.View$PerformClick.run(View.java:27351)
2021-12-23 21:34:28.476 26494-26494/com.wcc.jni.study W/System.err:     at android.os.Handler.handleCallback(Handler.java:883)
2021-12-23 21:34:28.476 26494-26494/com.wcc.jni.study W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:100)
2021-12-23 21:34:28.476 26494-26494/com.wcc.jni.study W/System.err:     at android.os.Looper.loop(Looper.java:214)
2021-12-23 21:34:28.477 26494-26494/com.wcc.jni.study W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:7356)
2021-12-23 21:34:28.477 26494-26494/com.wcc.jni.study W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2021-12-23 21:34:28.478 26494-26494/com.wcc.jni.study W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
2021-12-23 21:34:28.478 26494-26494/com.wcc.jni.study W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值