Java Native Interface(JNI)的空间(引用)管理

Java是通过垃圾回收机制回收内存,C/C++是通过malloc,free,new,delete手动管理空间。那么在JNI层,同时存在Java和C/C++的空间时,该如何进行空间的管理呢?本文参考Oracle的官方文档,对JNI层中空间的管理进行说明。明确哪些内容需要手动调用Delete,哪些不需要手动调用。

一、全局引用(Global References)

全局引用的生命周期(Lifetime),需要主动通过函数调用进行申请和释放。native函数执行完毕后,该空间可继续使用。

函数原型

// 创建全局引用
jobject NewGlobalRef(JNIEnv *env, jobject obj); // 删除全局引用
void DeleteGlobalRef(JNIEnv *env, jobject globalRef);

二、局部引用(Local References)

局部引用的生命周期(Lifetime),与调用的native函数一致。当native函数return时,局部引用将会被自动释放。该局部引用占用的空间是JVM的资源。

由于native函数用于存放局部引用的空间是固定的。如果过度的创建局部引用,不加以控制,可能会出现空间不足,程序抛出Out Of Memory(OOM)异常的问题。如果该局部引用已经使用完毕,应尽量手动调用DeleteLocalRef,提前释放空间,避免OOM。

函数原型

// 创建全局引用
jobject NewLocalRef(JNIEnv *env, jobject obj); // 删除全局引用
void DeleteLocalRef(JNIEnv *env, jobject localRef); // 主动设置可创建的局部引用的数量
jint EnsureLocalCapacity(JNIEnv *env, jint capacity); // 创建一个局部引用的帧,并指定可创建的局部引用的数量。
jint PushLocalFrame(JNIEnv *env, jint capacity); // 释放当前局部引用的帧,释放全部本地引用。
// 可以通过参数result,将被PopLocalFrame释放的引用转移到上一层的局部引用帧中
jobject PopLocalFrame(JNIEnv *env, jobject result);

特殊说明

  1. 在JDK/JRE 1.1版本中,提供了DeleteLocalRef函数。
  2. 在JDK/JRE 1.2版本中,提供了EnsureLocalCapacityPushLocalFramePopLocalFrameNewLocalRef函数,支持更加复杂的局部引用生命周期能力。

三、弱全局引用(Weak Global Reference)

区别于全局引用(Global References),该引用并不会增加该引用的引用计数。

即持有弱全局引用,不会干预垃圾回收机制(GC)对于该内存的回收。适用于生命周期短的对象,持有生命周期长的引用。

全局引用可以通过jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2); 函数,参数为被判定对象和NULL来判断对象是否存在。如果返回JNI_TRUE判定该弱引用指向的对象是否已经被释放。

使用弱全局引用时,可能会出现执行一半,引用被GC回收的情况。所以需要在使用弱全局引用之前,提供NewLocalRef或者NewGlobalRef,将弱引用转换为强引用。确保GC不会对该空间进行回收。

四、常见问题

1、在native函数中,直接return一个jstring或者其他jobject,是否会有内存泄漏问题?

如果直接return的对象是局部引用(Local Reference),则不会发生内存泄漏问题。

局部引用在native函数执行完毕后,会根据局部引用表(Local Reference Table)进行空间的释放。

当然,手动执行DeleteLocalRef函数进行提前释放,也不会产生问题。

2、什么情况下可能会出现内存泄漏?

1)创建的全局引用(Global Reference),未调用Delete函数进行回收。导致该对象引用计数无法归零。

2)两个对象互相持有对方的强引用。例如A持有B引用,B和C互相持有对方的引用。当A释放B引用时,GC发现C依然持有B的引用,则不会释放B。与此同时,GC也发现B持有C的引用,则不会释放C。导致B和C与其他引用脱离,形成孤岛。这块内存将无法使用,也无法被释放。

3、调用NewString和NewStringUTF时,是否需要释放?

NewStringNewStringUTF函数创建的空间属于局部引用(Local Reference)。可以等待native函数执行完毕后自动回收,也可以在使用完毕(后续不会再访问)后,直接进行Delete释放。

但是需要注意,如果通过GetStringCharsGetStringCritical或者GetStringUTFChars获取了jstring中的char* 空间,则需要使用对应的ReleaseStringCharsReleaseStringCritical或者ReleaseStringUTFChars释放该char* 空间。

参考文章

【GiraKoo】Java Native Interface(JNI)的空间(引用)管理的更多相关文章

  1. JAVA Native Interface (JNI)

    1.  Introduction At times, it is necessary to use native (non-Java) codes (e.g., C/C++) to overcome ...

  2. java native interface JNI 调用Java方法

    在上一篇文章中介绍了JNI.以及java调用JNI.这篇讲一下 JNI调用java方法. 通过使用合适的JNI函数,你能够创建Java对象,get.set 静态(static)和 实例(instanc ...

  3. Java Native Interface 基于JNI的嵌入式手机软件开发实例

    1.通过JNI和c/c++的库组件.其他代码交互 2.java和c不能互通的原因时数据类型问题 Introduction https://docs.oracle.com/javase/8/docs/t ...

  4. +Java中的native关键字浅析(Java+Native+Interface)++

    JNI是Java Native Interface的 缩写.从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的 ...

  5. Java Native Interface 五 JNI里的多线程与JNI方法的注册

    本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 JNI里的多线程 在本地方法里写有关多线程的 ...

  6. Java Native Interface 四--JNI中引用类型

    本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 JNI支持将类实例和数组类型(如jobjec ...

  7. Java Native Interface 二 JNI中对Java基本类型和引用类型的处理

    本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 Java编程里会使用到两种类型:基本类型(如 ...

  8. 【详解】JNI (Java Native Interface) (四)

    案例四:回调实例方法与静态方法 描述:此案例将通过Java调用的C语言代码回调Java方法. 要想调用实例对象的方法,需要进行以下步骤: 1. 通过对象实例,获取到对象类的引用  => GetO ...

  9. 【详解】JNI (Java Native Interface) (三)

    案例三:C代码访问Java对象的实例变量   获取对象的实例变量的步骤: 1. 通过GetObjectClass()方法获得此对象的类引用 2. 通过类引用的GetFieldID()方法获得实例变量的 ...

  10. 【详解】JNI (Java Native Interface) (二)

    案例二:传递参数给C代码,并从其获取结果 注:这里传递的参数是基本类型的参数,在C代码中有直接的映射类型. 此案例所有生成的所有文件如下: (1)编写案例二的Java代码,如下: 这里我们定义了一个n ...

随机推荐

  1. 【Apifox Helper】自动生成接口文档,IDEA+Apifox懒人必备

    @ 目录 前言 缘由 接口文档对接爽,整理起来真费脑 ⏲️本文阅读时长 约10分钟 前置条件 1. IDEA开发工具 2. Apifox(不必要) 主要目标 一秒生成接口文档 水图 IDEA中项目接结 ...

  2. ElasticSearch 实现分词全文检索 - match、match_all、multimatch查询

    目录 ElasticSearch 实现分词全文检索 - 概述 ElasticSearch 实现分词全文检索 - ES.Kibana.IK安装 ElasticSearch 实现分词全文检索 - Rest ...

  3. ECharts连接数据库的具体实现

    相关描述 我们由之前的实例可以得知,要是不连接数据库的话,只是需要套用一下ECharts的相关模板即可,这部分内容我在前几篇中已经叙述过了: 现在,我们需要实现的是,将数据库里面的数据导入到web网页 ...

  4. 使用containerd搭建MinIO集群服务

    概述 因为在云服务器上默认只有一块磁盘,如果直接在系统盘上安装MinIO,会被拒绝,所以这里采用containerd的方式绕过这一限制 操作环境 操作系统 CentOS 7.9 MinIO版本 REL ...

  5. fastposter v2.13.0 一分钟完成开发海报 [云服务来袭]

    fastposter v2.13.0 一分钟完成开发海报 [云服务来袭] fastposter海报生成器是一款快速开发海报的工具.只需上传一张背景图,在对应的位置放上组件(文字.图片.二维.头像)即可 ...

  6. AD域安全攻防实践(附攻防矩阵图)

    以域控为基础架构,通过域控实现对用户和计算机资源的统一管理,带来便利的同时也成为了最受攻击者重点攻击的集权系统. 01.攻击篇 针对域控的攻击技术,在Windows通用攻击技术的基础上自成一套技术体系 ...

  7. TCP 三次握手,给我长脸了噢

    大家好,我是小富~ 个人资源分享网站:FIRE 本文收录在 Springboot-Notebook 面试锦集 前言 之前有个小伙伴在技术交流群里咨询过一个问题,我当时还给提供了点排查思路,是个典型的八 ...

  8. RTE2021 回顾丨实践中的摸爬滚打,AI OPS 落地之路

    本文整理自声网Agora SD - RTN 网络传输质量负责人于涛在 RTE2021 实时互联网大会上的演讲分享.他在演讲中针对传统 OPS 痛点.AI OPS 的优势以及 AI OPS 工程化的难点 ...

  9. 机器学习算法(二): 基于鸢尾花数据集的朴素贝叶斯(Naive Bayes)预测分类

    机器学习算法(二): 基于鸢尾花数据集的朴素贝叶斯(Naive Bayes)预测分类 项目链接参考:https://www.heywhale.com/home/column/64141d6b1c8c8 ...

  10. Mybatis分页插件PageHelper的配置及使用方法

    尊重人家的知识成果 推荐 该作者总结的不错! --->> --->> @author 扎心了老铁 Mybatis分页插件PageHelper的配置及使用方法