NDK开发之JNI全局引用、局部引用、异常处理

时间:2022-12-12 12:10:40

本文为作者(石岩)原创,转载请指明出处:
https://blog.csdn.net/a1002450926/article/details/79812815

JAVA层代码

public class JniTest {

    public String key = "key:JniTest";

    // 局部引用
    public native void localRef();

    // 创建全局引用
    public native void createGlobalRef();

    // 获取全局引用
    public native String getGlobalRef();

    // 释放全局引用
    public native void deleteGlobalRef();

    // 异常
    public native void exception();

    public static void main(String[] args) {
        JniTest test = new JniTest();

        test.createGlobalRef();
        System.out.println(test.getGlobalRef());
        test.deleteGlobalRef();

        try {
            test.exception();
        } catch (Exception e) {
            System.out.println("Java层捕捉到了异常:" + e.getMessage());
        }
    }

    static {
        System.loadLibrary("JniTest");
    }
}

C层代码

#pragma once
#pragma execution_character_set("utf-8")

#define _CRT_SECURE_NO_WARNINGS
#include "com_shiyan_jni_JniTest.h"
#include<string.h>

/*
局部引用
模拟:循环创建数组
*/
JNIEXPORT void JNICALL Java_com_shiyan_jni_JniTest_localRef
(JNIEnv *env, jobject jobj){
    int i = 0;
    for (; i < 10; i++){
        jclass cls = (*env)->FindClass(env, "java/util/Date");
        jmethodID mid = (*env)->GetMethodID(env, cls, "<init>", "()V");
        jobject jobj = (*env)->NewObject(env, cls, mid);
        //通知垃圾回收期回收对象
        (*env)->DeleteLocalRef(env, jobj);
    }
}

//全局引用
jstring global_str;

/*
创建全局引用
*/
JNIEXPORT void JNICALL Java_com_shiyan_jni_JniTest_createGlobalRef
(JNIEnv *env, jobject jobj){
    jstring obj = (*env)->NewStringUTF(env, "hello jni!");
    global_str = (*env)->NewGlobalRef(env, obj);
}

/*
获取全局引用
*/
JNIEXPORT jstring JNICALL Java_com_shiyan_jni_JniTest_getGlobalRef
(JNIEnv *env, jobject jobj){
    return global_str;
}


/*
释放全局引用
*/
JNIEXPORT void JNICALL Java_com_shiyan_jni_JniTest_deleteGlobalRef
(JNIEnv *env, jobject jobj){
    (*env)->DeleteGlobalRef(env, global_str);
}

//弱全局引用
//节省内存,在内存不足时可以释放所引用的对象
//可以引用一个不常用的对象,如果为NULL,临时创建
//创建:NewWeakGlobalRef,销毁:DeleteGlobalWeakRef

/*
异常处理
*/
JNIEXPORT void JNICALL Java_com_shiyan_jni_JniTest_exception
(JNIEnv *env, jobject jobj){
    jclass cls = (*env)->GetObjectClass(env, jobj);
    jfieldID mid = (*env)->GetMethodID(env, cls, "key2", "Ljava/lang/String;");
    //检测是否发生java异常
    jthrowable exception = (*env)->ExceptionOccurred(env);

    if (exception != NULL){
        //让JAVA代码可以继续运行
        //清空异常信息
        (*env)->ExceptionClear(env);

        //补救措施
        mid = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
    }

    //获取属性的值
    jstring jstr = (*env)->GetObjectField(env, jobj, mid);
    //jstring->c
    char *str = (*env)->GetStringUTFChars(env, jstr, NULL);

    //判断是否相等
    if (_stricmp(str, "key:JniTest2") != 0){
        //认为抛出异常,给JAVA层处理
        jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
        (*env)->ThrowNew(env, newExcCls, "Key Value is not invalid!");
    }
}

结果演示

NDK开发之JNI全局引用、局部引用、异常处理