JNI优化之局部静态变量,MethodId,FeildId

本测试例子,采用java循环调用JNI方法获取一个字符串(JNI通过调用java的静态方法取到字符串)
Activity代码:

 public void testClick(View v) {
        long start = System.currentTimeMillis();
        JNI jni = new JNI();
        for (int i = 0; i < 2000000; i++) {
            jni.testCacheString(MainActivity.this);
        }
        long end = System.currentTimeMillis();
        Log.e(TAG, "JNI  计算的 2000000 读取字符串的 时间差:" + (end - start));
    }
    public static String getTestFromJava() {
        //Log.e(TAG, "执行了String:----------------------");
        return "o(* ̄︶ ̄*)o";
    }

JNI代码:

Java_com_sdke_fixdavid_JNI_testCacheString(JNIEnv *env, jobject instance, jobject object) {
    static jmethodID jmd = NULL;
//    jclass cls = env->FindClass("com/sdke/fixdavid/MainActivity");
    jclass cls = env->GetObjectClass(object);
    if (jmd == NULL) {
        jmd = env->GetStaticMethodID(cls, "getTestFromJava",
                                     "()Ljava/lang/String;");
        LOGE("加载Method方法-------------------");
    }
    jstring job = (jstring) env->CallStaticObjectMethod(cls, jmd);
    return job;
}

1、未优化之前
jclass cls = env->FindClass(“com/sdke/fixdavid/MainActivity”);
jmethodID jmd = env->GetStaticMethodID(cls, “getTestFromJava”,
“()Ljava/lang/String;”);
每次调用JNI方法都会去FindClass和获取方法Id,测试结果为:
JNI 计算的 2000000 读取字符串的 时间差:15280

2、将FindClass换成GetObjectClass
jclass cls = env->GetObjectClass(object);
测试结果:
JNI 计算的 2000000 读取字符串的 时间差:9651

3、使用局部静态变量存储MethodId
如代码中 static jmethodID jmd = NULL; 局部静态变量
会在方法第一次执行的时候初始化,随应用程序的关闭销毁

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

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

测试结果:
JNI 计算的 2000000 读取字符串的 时间差:6536

总结:
1、GetObjectClass在性能上是优于FindClass
2、程序多次调用MethodID或FieldID的时候,可使用静态变量存储,防止每次执行都调用

补充:

jclass globalClass = NULL;
extern "C"
JNIEXPORT jstring JNICALL
Java_com_sdke_fixdavid_JNI_testCacheString(JNIEnv *env, jobject instance, jobject object) {
    static jmethodID jmd = NULL;
//    jclass cls = env->FindClass("com/sdke/fixdavid/MainActivity");
//    jclass cls = env->GetObjectClass(object);
//    jmethodID jmd = env->GetStaticMethodID(cls, "getTestFromJava",
//                                                 "()Ljava/lang/String;");
    if (jmd == NULL) {
        jclass cls = env->GetObjectClass(object);
        globalClass = (jclass) env->NewGlobalRef(cls);
        env->DeleteLocalRef(cls);
        jmd = env->GetStaticMethodID(globalClass, "getTestFromJava",
                                     "()Ljava/lang/String;");
        LOGE("加载Method方法-------------------");
    }
    jstring job = (jstring) env->CallStaticObjectMethod(globalClass, jmd);
    return job;
}

将GetObjectClass 的class创建成全局变量,可以优化每次创建类的时间
globalClass = (jclass) env->NewGlobalRef(cls);

测试结果:
JNI 计算的 2000000 读取字符串的 时间差:4742

相关资料:
JNI全局局部变量,强弱引用

你可能感兴趣的:(JNI)