添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

做过Java的朋友都知道,内存管理这一块是完全透明的,new一个类的实例时,只知道创建完这个类的实例后,会返回这个实例的一个引用,然后拿着这个引用去访问它的成员了(属性、方法),完全不用管JVM内部怎么实现的,如何为新建的对象申请内存,使用完之后如何释放内存,只需要知道有个垃圾回收器在处理这些事情就行了,然而,从Java虚拟机创建的对象传到C/C++代码时会产生引用,根据Java的垃圾回收机制,只要有引用存在就不回触发该引用所指向Java对象的垃圾回收;这些引用在JNI 中分为3种:全局引用(Global Reference)、局部引用 (Local Reference)、弱全局引用 (Week Global Reference) since JDK1.2。

原文链接请标明:
http://blog.csdn.net/u011974987/article/details/52848908
本文出自:【 stromxu 的博客】

三种引用的区别

1、全局引用

全局引用可以跨方法、跨线程使用,直到被开发者显式释放。类似局部引用,一个全局引用在被释放前保证引用对象不被GC回收。和局部引用不同的是,没有那么多函数能够创建全局引用。能创建全局引用的函数只有 NewGlobalRef。以下例子说明了如何使用一个全局引用。

java native方法:

    public native void createGlobalRef();
    public native String getGlobalRef();
    public native void deleteGlobalRef();

jni实现:

//全局引用
//共享(可以跨多个线程),手动控制内存使用
jstring global_str;
JNIEXPORT void JNICALL Java_com_study_jni_JniTest_createGlobalRef(JNIEnv *env, jobject jobj){
    jstring obj = (*env)->NewStringUTF(env, "jni development is powerful!");
    global_str = (*env)->NewGlobalRef(env, obj);
JNIEXPORT jstring JNICALL Java_com_study_jni_JniTest_getGlobalRef(JNIEnv *env, jobject jobj){
    return global_str;
JNIEXPORT void JNICALL Java_com_study_jni_JniTest_deleteGlobalRef(JNIEnv *env, jobject jobj){
    (*env)->DeleteGlobalRef(env, global_str);
2、局部引用

一个局部引用仅在创建它的native函数及该函数调用的函数中有效。在一个native函数执行期间创建的所有局部引用将在该函数返回时被释放,创建了大量的局部引用,占用了太多的内存,而且这些局部引用跟后面的操作没有关联性。

//模拟:循环创建数组
JNIEXPORT void JNICALL Java_com_study_jni_JniTest_localRef(JNIEnv *env, jobject jobj){
    int i = 0;
    for (; i < 5; i++){
        //创建Date对象
        jclass cls = (*env)->FindClass(env, "java/util/Date");
        jmethodID constructor_mid = (*env)->GetMethodID(env, cls, "<init>", "()V");
        jobject obj = (*env)->NewObject(env, cls, constructor_mid);
        //此处省略一百行代码...
        //不在使用jobject对象了
        //通知垃圾回收器回收这些对象
        //释放局部引用
        (*env)->DeleteLocalRef(env, obj);
        //此处省略一百行代码...

上面代码中,省略了和我们无关紧要的代码,通过FindClass返回一个对java.util.Date对象的局部引用。

3、弱全局引用

节省内存,在内存不足时可以是释放所引用的对象,可以引用一个不常用的对象,如果为NULL,临时创建,弱全局引用使用NewGlobalWeakRef创建,使用DeleteGlobalWeakRef释放。下面简称弱引用。与全局引用类似,弱引用可以跨方法、线程使用。但与全局引用很重要不同的一点是,弱引用不会阻止GC回收它引用的对象,所以在使用时需要多加小心,它所引用的对象可能是不存在的或者已经被回收。

1.创建弱全局引用

用NewWeakGlobalRef函数对弱全局引用进行初始化,例如:

jclass weakGlobalcls
weakGlobalcls = (*env)->NewWeakGlobalRef(env,localclazz);
2.引用的比较

给定两个引用(不管是全局、局部还是弱全局引用),我们只需要调用IsSameObject来判断它们两个是否指向相同的对象。例如:(*env)->IsSameObject(env, obj1, obj2)
如果obj1和obj2指向相同的对象,则返回JNI_TRUE(或者1),否则返回JNI_FALSE(或者0)。有一个特殊的引用需要注意:NULL,JNI中的NULL引用指向JVM中的null对象。如果obj是一个局部或全局引用,使用(*env)->IsSameObject(env, obj, NULL) 或者 obj == NULL 来判断obj是否指向一个null对象即可。但需要注意的是,IsSameObject用于弱全局引用与NULL比较时,返回值的意义是不同于局部引用和全局引用的。比如:

if(JNI_FALSE == (*env)->IsSameObject(env,weakGlobalcls,NULL)){
//TODO 对象未被回收,可以使用
}else{
//TODO 对象被垃圾回收器回收,不能使用

以上就是学习这jni 的三种引用的简单使用,相关的知识并没有深入详细的说明!O(∩_∩)O~~

前言 做过Java的朋友都知道,内存管理这一块是完全透明的,new一个类的实例时,只知道创建完这个类的实例后,会返回这个实例的一个引用,然后拿着这个引用去访问它的成员了(属性、方法),完全不用管JVM内部怎么实现的,如何为新建的对象申请内存,使用完之后如何释放内存,只需要知道有个垃圾回收器在处理这些事情就行了,然而,从Java虚拟机创建的对象传到C/C++代码时会产生引用,根据Java的垃圾回 与局部引用对比 : 全局引用局部引用相对应 , 其作用域是全局的 , 局部引用只能在当前方法使用 ; 空间 : 可以 跨方法 , 跨线程使用 ; 时间 : 创建后可以使用 , 手动释放后全局引用失效 ; ( 手动释放前全局可用 )
转载请保留原文链接:http://blog.csdn.net/u010593680/article/details/41410289 附带宣传下参与的网站: 最爱明星网:http://zuiaimingxing.com/ 给自己的爱豆打call 最近的学习真的比较困难,因为学习了SDK开发项目后,做了一些简单的项目后,觉得在UI线程加载较多图片时,总会出现卡顿的感觉,特别是手指滑动下拉时,这...
上一篇博客向大家非常详细的介绍了JNI的字段和方法,想必大家都对JNI与Jvm交互有了更深刻的认识。Android NDK(五):字段和方法 本篇博客内容继续探索JNI,今天要和大家分享的内容是JNI引用。大家对引用肯定都不陌生了,我们每天所写的代码不知道有多少引用存在。JNI种的引用又是怎样的呢?一起来看看~ 内容会以引用的类型逐一分析,JNI支持三种引用类型,大致分类如下:
Android NDK开发是指利用NDK(Native Development Kit)将C/C++开发的代码编译成so库,然后通过JNI(Java Native Interface)让Java程序调用。在Android开发,默认使用的是Android SDK进行Java语言的开发,而对于一些需要使用C/C++的高性能计算、底层操作或跨平台需求的场景,可以使用NDK进行开发。 在Android Studio进行NDK开发相对于Eclipse来说更加方便,特别是在Android Studio 3.0及以上版本,配置更加简化,并引入了CMake等工具,使得开发更加便捷。首先要进行NDK开发,需要配置环境,包括导入NDK、LLDB和CMake等工具。可以通过打开Android Studio的SDK Manager,选择SDK Tools,在其相应的工具进行导入。 在项目的build.gradle文件,可以配置一些NDK相关的参数,例如编译版本、ABI过滤器等。其,可以通过externalNativeBuild配置CMake的相关设置,包括CMakeLists.txt文件的路径和版本号。此外,在sourceSets.main还可以设置jniLibs.srcDirs,指定so库的位置。 在进行NDK开发时,可以在jni文件夹编写C/C++代码,并通过JNI调用相关的函数。通过JNI接口,可以实现Java与C/C++之间的相互调用,从而实现跨语言的开发。 综上所述,Android NDK开发是指利用NDK将C/C++开发的代码编译成so库,并通过JNI实现与Java的相互调用。在Android Studio进行NDK开发相对方便,可以通过配置环境和相应的参数来进行开发。<span class="em">1</span><span class="em">2</span><span class="em">3</span>