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优化之局部静态变量,MethodId,FeildId】相关资料:
JNI全局局部变量,强弱引用

    推荐阅读