【GiraKoo】Java Native Interface(JNI)的空间(引用)管理
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);
特殊说明
- 在JDK/JRE 1.1版本中,提供了
DeleteLocalRef函数。 - 在JDK/JRE 1.2版本中,提供了
EnsureLocalCapacity,PushLocalFrame,PopLocalFrame,NewLocalRef函数,支持更加复杂的局部引用生命周期能力。
三、弱全局引用(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时,是否需要释放?
NewString和NewStringUTF函数创建的空间属于局部引用(Local Reference)。可以等待native函数执行完毕后自动回收,也可以在使用完毕(后续不会再访问)后,直接进行Delete释放。
但是需要注意,如果通过GetStringChars,GetStringCritical或者GetStringUTFChars获取了jstring中的char* 空间,则需要使用对应的ReleaseStringChars,ReleaseStringCritical或者ReleaseStringUTFChars释放该char* 空间。
参考文章
【GiraKoo】Java Native Interface(JNI)的空间(引用)管理的更多相关文章
- JAVA Native Interface (JNI)
1. Introduction At times, it is necessary to use native (non-Java) codes (e.g., C/C++) to overcome ...
- java native interface JNI 调用Java方法
在上一篇文章中介绍了JNI.以及java调用JNI.这篇讲一下 JNI调用java方法. 通过使用合适的JNI函数,你能够创建Java对象,get.set 静态(static)和 实例(instanc ...
- Java Native Interface 基于JNI的嵌入式手机软件开发实例
1.通过JNI和c/c++的库组件.其他代码交互 2.java和c不能互通的原因时数据类型问题 Introduction https://docs.oracle.com/javase/8/docs/t ...
- +Java中的native关键字浅析(Java+Native+Interface)++
JNI是Java Native Interface的 缩写.从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的 ...
- Java Native Interface 五 JNI里的多线程与JNI方法的注册
本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 JNI里的多线程 在本地方法里写有关多线程的 ...
- Java Native Interface 四--JNI中引用类型
本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 JNI支持将类实例和数组类型(如jobjec ...
- Java Native Interface 二 JNI中对Java基本类型和引用类型的处理
本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 Java编程里会使用到两种类型:基本类型(如 ...
- 【详解】JNI (Java Native Interface) (四)
案例四:回调实例方法与静态方法 描述:此案例将通过Java调用的C语言代码回调Java方法. 要想调用实例对象的方法,需要进行以下步骤: 1. 通过对象实例,获取到对象类的引用 => GetO ...
- 【详解】JNI (Java Native Interface) (三)
案例三:C代码访问Java对象的实例变量 获取对象的实例变量的步骤: 1. 通过GetObjectClass()方法获得此对象的类引用 2. 通过类引用的GetFieldID()方法获得实例变量的 ...
- 【详解】JNI (Java Native Interface) (二)
案例二:传递参数给C代码,并从其获取结果 注:这里传递的参数是基本类型的参数,在C代码中有直接的映射类型. 此案例所有生成的所有文件如下: (1)编写案例二的Java代码,如下: 这里我们定义了一个n ...
随机推荐
- 重构SeleniumeDownloader底层浏览器驱动
一.解决bug:Selenium with PhantomJS,重构SeleniumeDownloader底层浏览器驱动 0.小背景: 想爬取外网steam的数据,但是steam官网在海外,加上ste ...
- Android笔记--基础的连接数据库的操作
start.java package com.example.myapplication; import androidx.activity.result.ActivityResult; import ...
- PicList 现已上架Mac App Store 分享下整个上架过程和遇到的问题
PicList 是一款云存储/图床平台管理和文件上传工具,基于 PicGo 进行了深度二次开发,保留了 PicGo 的所有功能的同时,为相册添加了同步云端删除功能,同时增加了完整的云存储管理功能,包括 ...
- sdut——4541:小志志和小峰峰的日常(取石子博弈模板题 4合1)
小志志和小峰峰的日常 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 小志志和小峰峰特别喜欢一起讨论一些很好玩的问题. ...
- Flutter 2 渲染原理和如何实现视频渲染
7 月 17 日下午,在前端专场巡回沙龙北京站中,声网Agora跨平台开发工程师卢旭辉带来了<Flutter2 渲染原理和如何实现视频渲染>的主题分享,本文是对演讲内容的整理. 本次分享主 ...
- DVWA-SQL Injection(SQL注入)
SQL Injection,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的.结构,从而达到执行恶意SQL语句的目的. LOW: 代码审计: SQL Injection Source vuln ...
- Excel批量加粗关键词(宏)
代码如下: Sub 批量加粗() Dim a As Range Dim b As String b = InputBox("请输入要加粗的关键字") For Each a In A ...
- jason数组实现页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- broadcom Ethernet BCM57412 驱动更新记录(dkms方式)
一 背景 现场Dell R740xd2机器使用网卡Broadcom 57412 10Gb SFP+,固件版本22.21.06.80.bnxt_en.ko内核模块是该网卡的驱动,我们默认的驱动版本为1. ...
- 搭建Hadoop2.7.2和Hive2.3.3以及Spark3.1.2
Hadoop 简介 Hadoop是一个用Java编写的Apache开源框架,允许使用简单的编程模型跨计算机集群分布式处理大型数据集.Hadoop框架工作的应用程序在跨计算机集群提供分布式存储和计算的环 ...