首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【Android NDK 开发】JNI 引用 ( 局部引用 | 局部引用作用域 | 局部引用产生 | 局部引用释放 | 代码示例)

  • 25-02-16 05:21
  • 4425
  • 7823
blog.csdn.net

文章目录

        • I . JNI 引用数据类型
        • II . JNI 引用 与 指针
        • III . 局部引用 作用域
        • IV . 局部引用 产生 与 释放
        • V . 局部引用 代码示例



I . JNI 引用数据类型


1 . JNI 引用类型 : JNI 中 定义了 八种 Java 基本数据类型 , 其余的 jobject , jarray , jxxxArray , jclass , jstring 等都是引用类型 ;


① 规律 : 除 八种 基本数据类型之外的都是引用数据类型 ;

② 都是 Java 引用数据类型 : 这些数据类型都是 C/C++ 中定义的 Java 引用数据类型 , 其本质是 C/C++ 环境中对应的 Java 数据类型 ;


要注意将 JNI 中的 Java 类型引用 , 与 C/C++ 指针区分开 , 两者概念不同 ;


2 . JNI 引用类型分为三类 :


① 局部引用 : 其只在作用域内有效 , 内存不可回收 ;

② 全局引用 : 全局有效 , 内存不可回收 ;

③ 全局弱引用 : 全局有效 , 内存不足时会被 JVM 回收 ;


内存不可回收 , 如果内存不足 , 会直接 OOM 内存溢出 ;



II . JNI 引用 与 指针


在 JNI 中一定要将 引用 和 指针 区分开 ;

引用 是 Java 语言中的概念 , 指针 是 C/C++ 中的概念 ;

JNI 中 Java 引用类型 也是使用 C/C++ 指针表示的 , 这个 变量 就有了 两重含义 , 即代表 Java 中的引用类型 , 又代表了 编程环境中的 指针 ;

这里注意 , 如果引用被 JVM 释放了 , 即使指针还有值 , 也是不能用于 JNI 中与 Java 引用类型 相关的方法的 ;


本博客只讨论引用相关的内容 ;



III . 局部引用 作用域


1 . 局部引用作用域 :


局部引用只能在当前作用域有效 ;

超出作用域
手动释放
上面 两种情况 都会导致 局部引用变量 失效 ;


2 . 局部引用作用范围 :

① 空间 : 不能 跨线程 , 跨方法调用 , 仅在本作用域有效 ;

② 时间 : 创建后可以使用 , 手动释放 或 作用域结束 引用被释放不可使用 ;



IV . 局部引用 产生 与 释放


1 . 局部引用产生 与 释放 :

① 局部引用产生 : 使用 NewXXX / FindXXX 等 大多数 JNI 方法 默认创建的 Java 引用类型对象 都是局部引用 ;

② 局部引用释放 : 调用 DeleteLocalRef 方法 释放该局部引用 ;


2 . 局部引用的两种释放方式 :


① 自动释放 : 在方法作用域结束后 , JVM 自动释放上述 局部引用 变量 ;

② 手动释放 : 通过调用 DeleteLocalRef 方法手动释放 ;


3 . 局部引用推荐释放方式 :


① 内存角度考虑 : 局部引用 释放尽量灵活 , 不要等待自动释放 , 在使用完毕后 建议就手动释放 , 尽早回收内存 ;

② 自动释放情况 :如果该 引用 一直到最后都要使用 , 那么可以不进行手动释放 ;

③ 建议用法 : 局部引用建议都要手动释放 , 哪怕是在作用域最后 , 也要进行手动释放



V . 局部引用 代码示例


局部引用代码示例 :

extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniLocalReferenceTest(JNIEnv *env, jobject instance) {


    /*
        局部引用
            局部引用只能在当前作用域有效
                超出作用域
                手动释放
            上面 两种情况 都会导致 该局部变量都会失效


        局部引用作用范围 :
                空间 : 不能 跨线程 , 跨方法调用 , 仅在本作用域有效
                时间 : 创建后可以使用 , 手动释放 或 作用域结束 引用被释放不可使用

        局部引用 创建 : 使用 NewXXX / FindXXX 等 大多数 JNI 方法 默认创建的都是局部引用
                释放 : 调用 DeleteLocalRef 方法 释放该局部引用


        关于上面的三个创建的 局部引用 有两种释放方式
            方式一 : 在方法作用域结束后 , VM 自动释放上述变量
            方式二 : 通过调用 DeleteLocalRef 方法手动释放

        建议使用方式二 :
            局部引用 释放尽量灵活 , 不要等待自动释放 , 在使用完毕后 建议就手动释放 , 今早回收内存
            如果该 引用 一直到最后都要使用 , 那么可以不进行手动释放 ;

            建议用法 : 局部引用建议都要手动释放 , 哪怕是在作用域最后 , 也要进行手动释放

        局部引用传递到 Java 层 , 该传递是拷贝传递 , JNI 中该释放还是释放 , 不影响 Java 层使用


        引用概念 :
            这里要将 引用 和 指针的概区分清楚 ;
            class_teacher 引用在 作用域结束时 会被释放 , 不能将其用于 JNI 反射 Java 类的方法和字段
                          其指针值不为空 , 仍然有值 , 其仍然指向一个地址 , 但是地址中的数据被释放了

     */


    // 1 . 获取 Teacher 类 ( 该变量需要释放 )
    jclass class_teacher = env->FindClass("kim/hsl/jni/Teacher");

    // 2 .  查找构造方法
    jmethodID method_init = env->GetMethodID(class_teacher, "", "(ILjava/lang/String;)V");


    // 3 . 准备 Java 类型参数 ( 该变量需要释放 )
    //     此处特别注意 : 传入到 Java 方法中的参数都必须是 Java 参数
    jint teacher_age = 88;
    jstring teacher_name = env->NewStringUTF("Tom Wang");

    // 4 .  创建 Teacher 对象 ( 该变量需要释放 )
    jobject teacher = env->NewObject(class_teacher, method_init, teacher_age, teacher_name);

    // 5 .  释放上面通过 FindClass NewStringUTF NewObject 创建的引用变量 , 否则会造成内存泄漏
    //     使用完这三个引用之后 , 不再使用 ; 这里特别建议手动释放三个引用
    //     如果不手动释放 , 在 该引用 作用域 结束后 , 也会自动释放掉
    env->DeleteLocalRef(teacher_name);
    env->DeleteLocalRef(teacher);
    env->DeleteLocalRef(class_teacher);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
注:本文转载自blog.csdn.net的韩曙亮的文章"https://blog.csdn.net/shulianghan/article/details/104129744"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top