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

Android NDK开发之旅 目录

缓存策略

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

//局部静态变量进行缓存(使用时缓存)
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。






微信号kpioneer

推荐阅读更多精彩内容