android NDK 实用学习(四)-类缓存
1,为什么需要类缓存:
答:由于频繁的查找类及类成员变量需要很大的时间与空间开销,可参考如下文章:
http://www.ibm.com/developerworks/cn/java/j-jni/
http://www.28im.com/java/a2379737.html
2,缓存时需要在java类使用static,如下:
1 package com.dasea.test.core; 2 public class TestSetData { 3 // 主要是类ID和字段ID,方法ID的缓存 4 static { 5 OnNative(); 6 } 7 8 public native static void OnNative(); 9 10 public boolean bData; 11 public double dData; 12 public int iData; 13 public byte cData; 14 public String sData; 15 public byte byteArr[]; 16 17 public int intArr[]; 18 19 public TestSetData() { 20 // TODO Auto-generated constructor stub 21 bData = true; 22 dData = 100.11; 23 iData = 333; 24 cData = 100; 25 sData = "20150204"; 26 byteArr = new byte[10]; 27 for (int i = 0; i < byteArr.length; i++) { 28 byteArr[i] = '2'; 29 } 30 31 intArr = new int[10]; 32 for (int i = 0; i < intArr.length; i++) { 33 intArr[i] = i * 10; 34 } 35 } 36 }
3,c++端的相关实现代码:
①定义一个对应的结构体:
1 struct JTestSetData{ 2 jclass jtestSetData; 3 4 jfieldID jbData; 5 jfieldID jiData; 6 jfieldID jdData; 7 jfieldID jcData; 8 jfieldID jsData; 9 jfieldID jarrData; 10 };
②定义对应类的变量:
struct JTestSetData gs_testSetDataMgr;
③实现缓存函数:
1 JNIEXPORT void JNICALL Java_com_dasea_test_core_TestSetData_OnNative( 2 JNIEnv* env, jobject obj){ 3 DEBUG_OUT("TestSetData native start!"); 4 5 InitTestSetData(env); 6 7 DEBUG_OUT("TestSetData native end!"); 8 }
1 bool InitTestSetData(JNIEnv* env){ 2 // 缓存类及其字段 3 // 查找类里面的字段,并进行赋值 4 5 // STEP 1/3 : Load the class id 6 jclass jcSetDataMgr = env->FindClass("com/kq/rtk/core/TestSetData"); 7 8 // STEP 2/3 : Assign the ClassId as a Global Reference 9 gs_testSetDataMgr.jtestSetData = (jclass) env->NewGlobalRef(jcSetDataMgr); 10 11 jfieldID funB = env->GetFieldID(jcSetDataMgr, "bData", "Z"); 12 gs_testSetDataMgr.jbData = funB; 13 gs_testSetDataMgr.jiData = env->GetFieldID(jcSetDataMgr, "iData", "I"); 14 gs_testSetDataMgr.jdData = env->GetFieldID(jcSetDataMgr, "dData", "D"); 15 gs_testSetDataMgr.jcData = env->GetFieldID(jcSetDataMgr, "cData", "B"); 16 gs_testSetDataMgr.jsData = env->GetFieldID(jcSetDataMgr, "sData", "Ljava/lang/String;"); 17 gs_testSetDataMgr.jarrData = env->GetFieldID(jcSetDataMgr, "intArr", "[I"); 18 19 // STEP 3/3 : Delete the no longer needed local reference 20 env->DeleteLocalRef(jcSetDataMgr); 21 22 return true; 23 }
④使用缓存的类及成员:
java端接口:
public native void testPreCacheFun(TestSetData obj);
c++端实现:
1 JNIEXPORT void JNICALL Java_com_dasea_test_core_RTKNativeManager_testPreCacheFun( 2 JNIEnv* env, jobject obj, jobject jobj){ 3 DEBUG_OUT("testPreCache start!"); 4 5 if (NULL == gs_testSetDataMgr.jtestSetData) { 6 DEBUG_OUT("No cache class!"); 7 if(false == InitTestSetData(env)){ 8 DEBUG_OUT("Cache failed!"); 9 return ; 10 } 11 DEBUG_OUT("Cache success!"); 12 }else{ 13 DEBUG_OUT("Has cache!"); 14 } 15 16 env->SetBooleanField(jobj, gs_testSetDataMgr.jbData, false); 17 env->SetDoubleField(jobj, gs_testSetDataMgr.jdData, 209.22); 18 env->SetIntField(jobj, gs_testSetDataMgr.jiData, 3653); 19 env->SetByteField(jobj, gs_testSetDataMgr.jcData, 67); 20 21 DEBUG_OUT("Set field succ!"); 22 23 char data[10] = "jfkdsajfl"; 24 jstring sss = env->NewStringUTF(data); 25 env->SetObjectField(jobj, gs_testSetDataMgr.jsData, sss); 26 env->DeleteLocalRef(sss); 27 28 // 获取Java中数组属性arrays的对象 29 jintArray jint_arr = (jintArray)env->GetObjectField(jobj, gs_testSetDataMgr.jarrData); 30 int arrInt[10] = {0}; 31 for(int i = 0; i < 10; ++i){ 32 arrInt[i] = 300+i; 33 } 34 env->SetIntArrayRegion(jint_arr, 0, 10, arrInt); 35 36 DEBUG_OUT("testPreCache end!"); 37 }
⑤使用缓存类构造类对象:
1 DEBUG_OUT("AllocObject object !"); 2 jmethodID initID = env->GetMethodID(gs_testGetDataMgr.jtestGetData, "<init>", "()V"); 3 jobject jresult = env->NewObject(gs_testGetDataMgr.jtestGetData, initID);