JNI由淺入深_8_JNI緩存字段和方法ID

獲取字段ID和方法ID時,須要用字段、方法的名字和描述符進行一個檢索。檢索過程相對比較費時,所以本節討論用緩存技術來減小這個過程帶來的消耗。緩存字段ID和方法ID的方法主要有兩種。兩種區別主要在於緩存發生的時刻,是在字段ID和方法ID被使用的時候,仍是定義字段和方法的類靜態初始化的時候。java

一、使用時緩存android

字段ID和方法ID能夠在字段的值被訪問或者方法被回調的時候緩存起來。下面的代碼中把字段ID存儲在靜態變量當中,這樣當本地方法被重複調用時,沒必要從新搜索字段ID。程序員

JNIEXPORT void JNICALL 
 Java_InstanceFieldAccess_accessField(JNIEnv *env, jobject obj)
 {
     static jfieldID fid_s = NULL; /* cached field ID for s */
 
     jclass cls = (*env)->GetObjectClass(env, obj);
     jstring jstr;
     const char *str;
 
     if (fid_s == NULL) {
         fid_s = (*env)->GetFieldID(env, cls, "s", 
                                    "Ljava/lang/String;");
         if (fid_s == NULL) {
             return; /* exception already thrown */
         }
     }
 
     printf("In C:\n");
 
     jstr = (*env)->GetObjectField(env, obj, fid_s);
     str = (*env)->GetStringUTFChars(env, jstr, NULL);
     if (str == NULL) {
         return; /* out of memory */
     }
     printf("  c.s = \"%s\"\n", str);
     (*env)->ReleaseStringUTFChars(env, jstr, str);
 
     jstr = (*env)->NewStringUTF(env, "123");
     if (jstr == NULL) {
         return; /* out of memory */
     }
     (*env)->SetObjectField(env, obj, fid_s, jstr);
 }

二、初始化緩存緩存

許多狀況下,在字段ID和方法ID被使用前就初始化是很方便的。VM在調用一個類的方法和字段以前,都會執行類的靜態初始化過程,因此在靜態初始化該類的過程當中計算並緩存字段ID和方法ID是個不錯的選擇。函數

例如,爲了緩存InstanceMethodCall.callback的方法ID,咱們引入了一個新的本地方法initIDs,這個方法在InstanceMethodCall的靜態初始化過程當中被調用。

/**
 *  緩存ID
 */
jmethodID callbackStatic;


JNIEXPORT void JNICALL Java_com_example_jniandroid_service_CFunction_callJniNative2(
		JNIEnv * env, jobject obj) {
	LOGI("緩存了id...");
	(*env)->CallStaticVoidMethod(env, obj, callbackStatic);
}


JNIEXPORT void JNICALL Java_com_example_jniandroid_service_CFunction_initIDS(
		JNIEnv * env, jobject obj) {
	//調用靜態方法
	jclass cls = (*env)->GetObjectClass(env, obj);
	callbackStatic = (*env)->GetStaticMethodID(env, cls, "callbackStatic", "()V");
}

兩種緩存ID的方式之間的對比spa

若是JNI程序員不能控制方法和字段所在的類的源碼的話,在使用時緩存是個合理的方案。例如在MyNewString當中,咱們不能在String類中插入一個initIDs方法。code

比起靜態初始時緩存來講,使用時緩存有一些缺點:orm

一、使用時緩存的話,每次使用時都要檢查一下。blog

二、方法ID和字段ID在類被unload時就會失效,若是你在使用時緩存ID,你必須確保只要本地代碼依賴於這個ID的值,那麼這個類不被會unload(下一章演示瞭如何經過使用JNI函數建立一個類引用來防止類被unload)。另外一方面,若是緩存發生在靜態初始化時,當類被unload和reload時,ID會被從新計算。ip

所以,儘量在靜態初始化時緩存字段ID和方法ID。

相關文章
相關標籤/搜索