Android NDK开发之旅15 JNI 缓存策略

本文介绍两种JNI缓存策略:一是通过局部静态变量进行缓存,适用于频繁调用的方法;二是动态库加载时初始化全局变量,适用于整个应用程序生命周期内的缓存需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

###缓存策略

####一、局部静态变量进行缓存:

//局部静态变量进行缓存(使用时缓存)
JNIEXPORT void JNICALL Java_com_haocai_jni_JniTest_cached
(JNIEnv *env, jobject obj) {
	jclass cls = (*env)->GetObjectClass(env, obj);


	//获取jfieldID只获取一次
	//局部静态变量
	static jfieldID key_id = NULL;
	if (key_id == NULL) {
		key_id = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
		printf("---------GetFieldID---------\n");
	}
}
复制代码

测试:

public native void cached();

public static void main(String[] args) {

    JniTest jniTest= new JniTest();
    //不断调用cached方法
    for (int i = 0; i < 100; i++) {
        jniTest.cached();
    }
}

结果输出:
---------GetFieldID---------
复制代码

####特点:

获取jfieldID只获取一次。局部静态变量只能在本方法的作用域中使用。

局部静态变量的生命周期:

  • 初始化,函数第一次执行
  • 结束,作用域被销毁了,但是这个变量还会存在内存当中,直到程序结束。

####二、动态库加载的时候初始化全局变量 #####就是在任何native函数调用前把id全部存起来。我们可以让java在第一次加载这类的时候首先调用本地代码初始化所有的jfieldID/jmethodID。

C代码如下:

//初始化两个全局变量,动态库加载完成之后,立刻缓存起来
//以后可以在其他函数使用,声明周期也是跟应用程序(进程)一致
//初始化全局变量
jfieldID key_fid;
jmethodID random_mid;

//局部静态变量进行缓存
JNIEXPORT void JNICALL Java_com_haocai_jni_JniTest_cached
(JNIEnv *env, jobject obj) {
	jclass cls = (*env)->GetObjectClass(env, obj);
	//获取jfieldID只获取一次
	//局部静态变量
	static jfieldID key_id = NULL;
	if (key_id == NULL) {
		key_id = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
		printf("---------GetFieldID---------\n");
	}
	if (key_fid == NULL) {
		printf("---------key_fid2---------\n");
	}
	if (random_mid == NULL) {
		printf("---------random_mid2---------\n");
	}
}

//动态库加载的时候初始化全局变量
JNIEXPORT void JNICALL Java_com_haocai_jni_JniTest_initIds
(JNIEnv *env, jclass cls) { //注意静态声明时第二个参数为jclasss
	key_fid = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
	printf("---------key_fid---------\n");
	random_mid = (*env)->GetMethodID(env, cls, "genRandomInt", "(I)I");
	printf("---------random_mid---------\n");
	
}
复制代码

测试:

public class JniTest {
    public native void cached();
    public native static void initIds();

    public static void main(String[] args) {
        JniTest jniTest = new JniTest();
        //不断调用cached方法
        for (int i = 0; i < 100; i++) {
            jniTest.cached();
        }
    }

    //产生指定范围的随机数
    public int genRandomInt(int max) {
        System.out.println("genRandomInt 执行了..");
        return new Random().nextInt(max);
    }
    static {
        System.loadLibrary("jni1");
        initIds();//C中全局变量初始化
    }
}


结果输出:
---------key_fid---------
---------random_mid---------

---------GetFieldID---------

复制代码

####特点: 1.省去局部静态变量进行缓存要确定id是否存在的语句(if(id==null){...})。 2当java类卸载或是重新加载的手也会重新呼叫该本地代码来重新计算IDs。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值