局部引用
- 局部引用
- 定义方式多样:FindClass、NewObject、GetObjectClass、NewCharArray、…NewLocalRef()
- 释放方式:1、方法调用完JVM会自动释放 2、DeleteLocalRef 3、JNI对局部引用限制为512个,所以应该用完即释放
- 不能在多线程里面使用
JNIEXPORT void JNICALL Java_zzqqiang_1Test_localRef
(JNIEnv * env, jobject jobj) {
int i = 0;
for(int i=0;i<5;i++) {
jclass cls = (*env)->FindClass(env,"java/util/Data");
jmethodID jmid = (*env)->GetMethodID(env,cls,“<init>”,"()V");
//创建一个Date类型的局部引用
jobject obj = (*env)->NewObject(env,cls,jmid);
//使用这个引用
//释放引用
(*env)->DeleteLocalRef(env,cls);
(*env)->DeleteLicalRef(env,obj);
}
}
//java
public class JniMain {
public native void localRef();
}
全局引用
- 跨线程、跨方法使用
- NewGlobalRef 是创建全局引用的唯一方法
jstring global_str;
JNIEXPORT void JNICALL Java_com_zzqqiang_1Test_createGlobalRef
(JNIEnv * env, jobject jobj) {
jobject obj = (*env)->NewStringUTF(env, "JNI is intersting");
global_str = (*env)->NewGlobalRef(env, obj);
}
JNIEXPORT jstring JNICALL Java_com_zzqqiang_Jni_1Test_getGlobalRef
(JNIEnv * env, jobject jobj) {
return global_str;
}
//用完后进行释放
JNIEXPORT void JNICALL Java_com_zzqqiang_Jni_1Test_delGlobalRef
(JNIEnv * env, jobject jobj) {
(*env)->DeleteGlobalRef(env, global_str);
}
弱全局引用
- 它不会阻止GC
- 跨线程,跨方法使用
jclass g_weak_cls;
JNIEXPORT jstring JNICALL Java_com_zzqqiang_Jni_1Test_createWeakRef
(JNIEnv * env, jobject jobj) {
jclass cls_string = (*env)->FindClass(env, "java/lang/String");
g_weak_cls = (*env)->NewWeakGlobalRef(env, cls_string);
return g_weak_cls;
}
缓存策略与弱引用联合使用带来的问题
当内存不够的清空下会发生gc,从而导致静态变量指向的内存被释放,这个时候继续获取静态的值就会出现异常
//缓存策略和弱引用联合使用带来的问题
JNIEXPORT jstring JNICALL Java_JniMain_AcessCacheNewString
(JNIEnv * env, jobject jobj) {
//定义一个静态的局部变量
static jclass cls_string = NULL;
if (cls_string == NULL)
{
printf("alvin in Java_JniMain_AcessCache_newString out: \n");
//给局部静态变量赋一个局部引用
cls_string = (*env)->FindClass(env, "com/zzqqiang/alvin/Refrence");
}
//使用这个静态局部变量
jmethodID jmid = (*env)->GetMethodID(env, cls_string, "getRef", "(I)I");
jthrowable ex = (*env)->ExceptionOccurred(env);
if (ex != NULL)
{
jclass newExc;
// 让java 继续运行
(*env)->ExceptionDescribe(env);//输出关于这个异常的描述
(*env)->ExceptionClear(env);
printf("C exceptions happend\n");
}
printf("alvin out Java_JniMain_AcessCache_newString\n");
return NULL;
}
//java
public class JniMain{
public native String AcessCacheNewString();
public static void main(String[] args) {
JniMain jniMain = new JniMain();
for(int i = 0; i < 100; i++) {
jniMain.AcessCF();
//触发gc回收
long[] ar = new long[1024*1024*100];
}
}
}
网友评论