缓存策略
一、局部静态变量进行缓存:
//局部静态变量进行缓存(使用时缓存)
JNIEXPORT void JNICALL Java_com_haocai_jni_JniTest_cached
(JNIEnv *env, jobject obj) {
jclass cls = (*env)->GetObjectClass(env, obj);
//获取jfieldID只获取一次
//局部静态变量
static jfieldID key_id = NULL;
if (key_id == NULL) {
key_id = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
printf("---------GetFieldID---------\n");
}
}
测试:
public native void cached();
public static void main(String[] args) {
JniTest jniTest= new JniTest();
//不断调用cached方法
for (int i = 0; i < 100; i++) {
jniTest.cached();
}
}
结果输出:
---------GetFieldID---------
特点:
获取jfieldID只获取一次。局部静态变量只能在本方法的作用域中使用。
局部静态变量的生命周期:
- 初始化,函数第一次执行
- 结束,作用域被销毁了,但是这个变量还会存在内存当中,直到程序结束。
二、动态库加载的时候初始化全局变量
就是在任何native函数调用前把id全部存起来。我们可以让java在第一次加载这类的时候首先调用本地代码初始化所有的jfieldID/jmethodID。
C代码如下:
//初始化两个全局变量,动态库加载完成之后,立刻缓存起来
//以后可以在其他函数使用,声明周期也是跟应用程序(进程)一致
//初始化全局变量
jfieldID key_fid;
jmethodID random_mid;
//局部静态变量进行缓存
JNIEXPORT void JNICALL Java_com_haocai_jni_JniTest_cached
(JNIEnv *env, jobject obj) {
jclass cls = (*env)->GetObjectClass(env, obj);
//获取jfieldID只获取一次
//局部静态变量
static jfieldID key_id = NULL;
if (key_id == NULL) {
key_id = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
printf("---------GetFieldID---------\n");
}
if (key_fid == NULL) {
printf("---------key_fid2---------\n");
}
if (random_mid == NULL) {
printf("---------random_mid2---------\n");
}
}
//动态库加载的时候初始化全局变量
JNIEXPORT void JNICALL Java_com_haocai_jni_JniTest_initIds
(JNIEnv *env, jclass cls) { //注意静态声明时第二个参数为jclasss
key_fid = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
printf("---------key_fid---------\n");
random_mid = (*env)->GetMethodID(env, cls, "genRandomInt", "(I)I");
printf("---------random_mid---------\n");
}
测试:
public class JniTest {
public native void cached();
public native static void initIds();
public static void main(String[] args) {
JniTest jniTest = new JniTest();
//不断调用cached方法
for (int i = 0; i < 100; i++) {
jniTest.cached();
}
}
//产生指定范围的随机数
public int genRandomInt(int max) {
System.out.println("genRandomInt 执行了..");
return new Random().nextInt(max);
}
static {
System.loadLibrary("jni1");
initIds();//C中全局变量初始化
}
}
结果输出:
---------key_fid---------
---------random_mid---------
---------GetFieldID---------
特点:
1.省去局部静态变量进行缓存要确定id是否存在的语句(if(id==null){...})。
2当java类卸载或是重新加载的手也会重新呼叫该本地代码来重新计算IDs。
网友评论