JNI最適化の局所静的変数,MethodId,FeildId

3102 ワード

このテスト例では、Javaループ呼び出し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が計算した200000文字列の読み出し時間差:15280です.
2、FindClassをGetObjectClass jclass=env->GetObjectClass(object)に変更する.試験結果:JNIが計算した200000文字列の読み出し時間差:9651
3、局所静的変数を用いてMethodIdをコード中のstatic jmethodID jmd=NULLのように記憶する.ローカル静的変数は、メソッドが最初に実行されたときに初期化され、アプリケーションのクローズに伴って破棄されます.
ローカル静的変数のライフサイクル:
1、初期化、関数は初めて2、終了し、役割ドメインは破棄されたが、この変数はプログラムが終了するまでメモリに存在する.
テスト結果:JNIが計算した200000文字列の読み出し時間差: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が計算した200000文字列の読み出し時間差:4742
関連資料:JNIグローバルローカル変数、強弱引用