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

作者: 香沙小熊 | 来源:发表于2017-11-08 19:16 被阅读140次

    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

    相关文章

      网友评论

        本文标题:Android NDK开发之旅15--JNI--缓存策略

        本文链接:https://www.haomeiwen.com/subject/sshymxtx.html