android NDK 实用学习(四)-类缓存

时间:2021-11-16 12:21:32

1,为什么需要类缓存:

答:由于频繁的查找类及类成员变量需要很大的时间与空间开销,可参考如下文章:

http://www.ibm.com/developerworks/cn/java/j-jni/

http://www.28im.com/java/a2379737.html

2,缓存时需要在java类使用static,如下:

 package com.dasea.test.core;
public class TestSetData {
// 主要是类ID和字段ID,方法ID的缓存
static {
OnNative();
} public native static void OnNative(); public boolean bData;
public double dData;
public int iData;
public byte cData;
public String sData;
public byte byteArr[]; public int intArr[]; public TestSetData() {
// TODO Auto-generated constructor stub
bData = true;
dData = 100.11;
iData = 333;
cData = 100;
sData = "20150204";
byteArr = new byte[10];
for (int i = 0; i < byteArr.length; i++) {
byteArr[i] = '2';
} intArr = new int[10];
for (int i = 0; i < intArr.length; i++) {
intArr[i] = i * 10;
}
}
}

3,c++端的相关实现代码:

①定义一个对应的结构体:

 struct JTestSetData{
jclass jtestSetData; jfieldID jbData;
jfieldID jiData;
jfieldID jdData;
jfieldID jcData;
jfieldID jsData;
jfieldID jarrData;
};

②定义对应类的变量:

struct JTestSetData gs_testSetDataMgr;

③实现缓存函数:

 JNIEXPORT void JNICALL Java_com_dasea_test_core_TestSetData_OnNative(
JNIEnv* env, jobject obj){
DEBUG_OUT("TestSetData native start!"); InitTestSetData(env); DEBUG_OUT("TestSetData native end!");
}
 bool InitTestSetData(JNIEnv* env){
// 缓存类及其字段
// 查找类里面的字段,并进行赋值 // STEP 1/3 : Load the class id
jclass jcSetDataMgr = env->FindClass("com/kq/rtk/core/TestSetData"); // STEP 2/3 : Assign the ClassId as a Global Reference
gs_testSetDataMgr.jtestSetData = (jclass) env->NewGlobalRef(jcSetDataMgr); jfieldID funB = env->GetFieldID(jcSetDataMgr, "bData", "Z");
gs_testSetDataMgr.jbData = funB;
gs_testSetDataMgr.jiData = env->GetFieldID(jcSetDataMgr, "iData", "I");
gs_testSetDataMgr.jdData = env->GetFieldID(jcSetDataMgr, "dData", "D");
gs_testSetDataMgr.jcData = env->GetFieldID(jcSetDataMgr, "cData", "B");
gs_testSetDataMgr.jsData = env->GetFieldID(jcSetDataMgr, "sData", "Ljava/lang/String;");
gs_testSetDataMgr.jarrData = env->GetFieldID(jcSetDataMgr, "intArr", "[I"); // STEP 3/3 : Delete the no longer needed local reference
env->DeleteLocalRef(jcSetDataMgr); return true;
}

④使用缓存的类及成员:

java端接口:

public native void testPreCacheFun(TestSetData obj);

c++端实现:

 JNIEXPORT void JNICALL Java_com_dasea_test_core_RTKNativeManager_testPreCacheFun(
JNIEnv* env, jobject obj, jobject jobj){
DEBUG_OUT("testPreCache start!"); if (NULL == gs_testSetDataMgr.jtestSetData) {
DEBUG_OUT("No cache class!");
if(false == InitTestSetData(env)){
DEBUG_OUT("Cache failed!");
return ;
}
DEBUG_OUT("Cache success!");
}else{
DEBUG_OUT("Has cache!");
} env->SetBooleanField(jobj, gs_testSetDataMgr.jbData, false);
env->SetDoubleField(jobj, gs_testSetDataMgr.jdData, 209.22);
env->SetIntField(jobj, gs_testSetDataMgr.jiData, );
env->SetByteField(jobj, gs_testSetDataMgr.jcData, ); DEBUG_OUT("Set field succ!"); char data[] = "jfkdsajfl";
jstring sss = env->NewStringUTF(data);
env->SetObjectField(jobj, gs_testSetDataMgr.jsData, sss);
env->DeleteLocalRef(sss); // 获取Java中数组属性arrays的对象
jintArray jint_arr = (jintArray)env->GetObjectField(jobj, gs_testSetDataMgr.jarrData);
int arrInt[] = {};
for(int i = ; i < ; ++i){
arrInt[i] = +i;
}
env->SetIntArrayRegion(jint_arr, , , arrInt); DEBUG_OUT("testPreCache end!");
}

⑤使用缓存类构造类对象:

      DEBUG_OUT("AllocObject object !");
jmethodID initID = env->GetMethodID(gs_testGetDataMgr.jtestGetData, "<init>", "()V");
jobject jresult = env->NewObject(gs_testGetDataMgr.jtestGetData, initID);