本测试例子,采用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全局局部变量,强弱引用