调用DeleteLocalRef的正确姿势
做安卓jni相关开发的总会在涉及到jni变量释放时怀疑人生,what? where? when? who? why? how? how much?
最近碰到一个比较奇怪的问题,有一个jni方法的耗时在随着调用次数的增加而上涨,但是没有明显的内存泄漏,经过我缜密分析之后,终于解决了深埋多年的疑惑。代码如下:
void HENativeUtils::vectorFloatToJArray(JNIEnv* env, const std::vector<float>& src, jobject obj, jfieldID fieldId)
{jfloatArray jArray = ( jfloatArray )env->GetObjectField(obj, fieldId);if (!jArray || env->GetArrayLength(jArray) != src.size()){jArray = env->NewFloatArray(src.size());env->SetObjectField(obj, fieldId, jArray);}jfloat* array = env->GetFloatArrayElements(jArray, nullptr);std::copy(src.begin(), src.end(), array);env->ReleaseFloatArrayElements(jArray, array, 0);
}
这个方法提供了对一个java对象obj中的float[]成员变量进行操作的功能,如果该对象为空或者size与需要被设置的对象size不一致则创建一个新的float[]并覆盖该对象。从上面代码可知我在使用完成后已经调用env->ReleaseFloatArrayElements将对应的jni数组释放,为什么还存在泄漏?甚至有动手能力比较强的小伙伴如果把这段代码复制到自己的jni代码中去调用,可能也不会有泄漏。
关于类似这种jfloatArray/jintArray/jbyteArray等等对象什么时候需要调用env->ReleaseFloatArrayElements很多稍微有点经验的小伙伴都知道,但是关于什么时候需要调用env->DeleteLocalRef,相信很多人都会比较模糊。
上面这段代码之所以存在泄漏,关键在于调用环境的差异。
当我们从java线程中调用cpp代码,这时候每个jni方法都会带一个JNIEnv*,这个JNIEnv就代表了这个java线程,在这个jni方法中调用上面的方法就很正常,因为这个jni会在方法结束后自动DetachCurrentThread,这个自动调用相当关键,就会自动清理掉jni中类似jfloatArray/jintArray/jbyteArray的局部变量。
相对应的,还有一种情况就是我们在cpp中创建的线程,当我们想在该线程中调用java的方法,通常会调用JavaVm的AttachCurrentThread来为当前线程获取一个JNIEnv*,并且在一条长时间运行的后台线程中只要我AttachCurrentThread并获取JNIEnv*之后我就可以一直使用这个JNIEnv*来调用java方法。这个时候就很容易出问题了,因为这个线程的生命相当长,而我们每次在这个线程中调用方法vectorFloatToJArray时都会有一个新的局部变量jfloatArray,在我们自己创建的回调方法中没有自动的DetachCurrentThread,所以这个变量就泄漏了。值得注意的是,如果存在cpp线程->java方法->jni方法,此时这个jni方法虽然看起来长得和从java线程调过来的方法一模一样,但是相差甚远的是其JNIEnv*代表的其实还是前面AttachCurrentThread所获得的,如果之前没有手动调用过DetachCurrentThread,这里也一样会泄漏。
上面的方法保险起见应该加上一行env->DeleteLocalRef()
void HENativeUtils::vectorFloatToJArray(JNIEnv* env, const std::vector<float>& src, jobject obj, jfieldID fieldId)
{jfloatArray jArray = ( jfloatArray )env->GetObjectField(obj, fieldId);if (!jArray || env->GetArrayLength(jArray) != src.size()){jArray = env->NewFloatArray(src.size());env->SetObjectField(obj, fieldId, jArray);}jfloat* array = env->GetFloatArrayElements(jArray, nullptr);std::copy(src.begin(), src.end(), array);env->ReleaseFloatArrayElements(jArray, array, 0);env->DeleteLocalRef(jArray);
}
正确姿势有两种(二选一就好了):
- 在每个cpp子线程调用java方法结束后都DetachCurrentThread
- 在每个继承自jobject对象的局部变量后面都加上env->DeleeteLocalRef()
相关文章:
调用DeleteLocalRef的正确姿势
做安卓jni相关开发的总会在涉及到jni变量释放时怀疑人生,what? where? when? who? why? how? how much? 最近碰到一个比较奇怪的问题,有一个jni方法的耗时在随着调用次数的增加而上涨,但是没有明显的内存泄漏,经过我缜密分…...
抖音小店从0到1起店流程,实操经验分享!
我是电商珠珠 很多人在开店之后,并不知道怎么做。往往会有人跑来问我说,开店之后怎么做啊,流程方面我还不是很熟悉啊等等。 这份起店流程备好了,将来对你有用。 第一步,店铺基础设置 在店铺开好之后,不…...
MySQL权限
权限 MySQL 允许客户端用户连接到服务器并访问服务器管理数据,MySQL 用户权限系统的主要功能是对给定主机连接的用户进行身份验证,并将该用户与数据库的权限相关联。 在 MySQL8 之前,授权表使用 MyISAM 并且是非事务性的,在 MyS…...
Nginx服务器安装证书并启用SSL(acme.sh)
前提 您已购置vps服务器,例如阿里云全球站ecs、AWS EC2、Azure VM、GCP Compute等安全组已开启80、443端口,且访问源设置为0.0.0.0/0域名已设置A记录指向当前操作服务器,若您使用aws ec2,有公有 IPv4 DNS,可供使用 安…...
c++实现观察者模式
前言 我觉得这是最有意思的模式,其中一个动,另外的自动跟着动。发布-订阅,我觉得很巧妙。 代码 头文件 #pragma once #include<vector> #include<string> #include<iostream>// 抽象观察者 class Aobserver { public:v…...
C 语言左移位操作在kernel驱动子系统中的特殊用途
文章目录 前言一、C语言左移位操作介绍1. 左移位二、左移位操作在kernel 驱动子系统中的应用1. 左移位操作在 V4L2, Media 子系统中的应用实例2.左移位操作在 DRM 子系统中的应用实例2.1 左移位操作在struct drm_crtc 中的应用2.2 左移位操作在struct drm_encoder 中的应用总结…...
kafka3.6.0集群部署
环境准备 机器环境 系统主机名IP地址centos7.9kafka01192.168.200.51centos7.9kafka02192.168.200.52centos7.9kafka03192.168.200.53 所需软件 jdk-8u171-linux-x64.tar.gzapache-zookeeper-3.8.3-bin.tar.gz https://dlcdn.apache.org/zookeeper/zookeeper-3.8.3/apache-zook…...
JAVA客户端使用账号密码调用influxdb2报错:{“code“:“unauthorized“,“message“:“Unauthorized“}
问题:JAVA客户端访问influxdb2报错 说明:当前influxdb版本:2.6.1 使用依赖: <dependency><groupId>org.influxdb</groupId><artifactId>influxdb-java</artifactId><version>2.10</vers…...
Mysql查询今天到期、n天即将到期、还有n天过期相关sql
超级治愈的一段话 其实你已经很幸福了,吃饱穿暖,没病没灾,隔三岔五还能吃顿好的,偶尔还能睡到自然醒,肥嘟嘟的一身福气。人这一辈子,要是能够逃过天灾,躲过战乱,不遇歹人,不生大病,就已经是非常幸运了,要是还能家庭和谐,收人稳定,三五知己,那更是天大的福泽。 -…...
【漏洞复现】Apache Log4j Server 反序列化命令执行漏洞(CVE-2017-5645)
感谢互联网提供分享知识与智慧,在法治的社会里,请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证 1.5、深度利用1、反弹Shell 说明内容漏洞编号CVE-2017-5645漏洞名称Log4j Server …...
【江协科技-用0.96寸OLED播放知名艺人打篮球视频】
Python进行视频图像处理,通过串口发送给stm32,stm32接收数据,刷新OLED进行显示。 步骤: 1.按照接线图连接好硬件 2.把Keil工程的代码下载到STM32中 3.运行Python代码,通过串口把处理后的数据发送给STM32进行显示 …...
CATIA环境编辑器用不了时创建项目快捷方式
CATIA环境编辑器用不了时创建项目快捷方式 一、参考适用情况示例二、 解决步骤(一) 先正确放置winb_64部署包(二) 添加环境文件(三) 修改加入的环境文件(四) 复制本机CATIA快捷方式后重命名(五) 修改快捷方式目标的值 一、参考适用情况示例 二、 解决步骤 (一) 先正确放置winb…...
java泛型的深入 泛型还可以在很多地方进行定义 泛型类 泛型方法 泛型接口 泛型的继承和通配符 泛型类练习
文章目录 泛型的深入泛型还可以在很多地方进行定义泛型类泛型方法泛型接口 泛型的继承和通配符泛型类练习总结 泛型的深入 public static void main(String[] args) {//在没有泛型的时候怎么存储数据ArrayList listnew ArrayList();list.add(1);list.add("abc");//遍…...
持续交付的好处
在软件领域,持续交付就是这样一种开发实践,它为所有利益相关者带来好处:开发、运营、测试人员和业务团队。持续交付适用于每个由软件驱动的组织;很难想象企业不使用软件。 它使人们受益,并需要人们做出改变才能更好地…...
APP开发:用途与未来前景|软件定制开发|网站小程序建设
APP开发:用途与未来前景|软件定制开发|网站小程序建设 APP开发已成为现代科技趋势的一部分,无论是日常生活还是商业领域,都有它的身影。通过开发APP,我们可以将想法、功能和内容转化为直观、易用的移动设备应用程序,满…...
图论——并查集
参考内容: 图论——并查集(详细版) 并查集(Disjoint-set)是一种精巧的树形数据结构,它主要用于处理一些不相交集合的合并及查询问题。一些常见用途,比如求联通子图、求最小生成树的 Kruskal 算法和求最近公共祖先&…...
计算机毕业设计java+vue+springboot的论坛信息网站
项目介绍 本论文系统地描绘了整个网上论坛管理系统的设计与实现,主要实现的功能有以下几点:管理员;首页、个人中心、用户管理、公告管理、公告类型管理、热门帖子管理、帖子分类管理、留言板管理、论坛新天地、我的收藏管理、系统管理&#…...
.net core添加SQL日志输出
GreDbContext : Microsoft.EntityFrameworkCore.DbContext 下添加 public static readonly ILoggerFactory MyLoggerFactory LoggerFactory.Create(builder > { builder.AddConsole(); }); protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder…...
虚幻5.1 常见的效果关闭方式
常见的虚幻效果关闭方式 1.Bloom ProjectSettings->Rendering->Default Settings->Bloom PostProcessVolume->Lens->Bloom 2.Ambient Occlusion/Screen Space Ambient Occlusion(SSAO) ProjectSettings->Rendering->Default Settings->Ambient Occl…...
每日一题 --- 力扣318----最大单词长度乘积
这道题时间复杂度我感觉设置的不是很好,应该最好是有一个1000变成10000就行。 因为我在做这道题的时候被误导了,以为双重循环暴力判断一下也能过,因为1000*1000 *26的时间复杂度没有到1亿,那么我刚开始认为是能过的,结…...
别再手动点菜单了!用这招让Cadence Virtuoso Schematic效率翻倍(附Net高亮快捷键配置)
电路设计效率革命:Cadence Virtuoso Schematic高阶快捷键配置指南 在集成电路设计的浩瀚宇宙中,Cadence Virtuoso如同设计师手中的光刻机,每一次精准操作都直接影响最终芯片的性能与可靠性。然而,当面对数百个晶体管组成的复杂模…...
Redis沙盒体验:在浏览器中零门槛掌握NoSQL核心技能
Redis沙盒体验:在浏览器中零门槛掌握NoSQL核心技能 【免费下载链接】try.redis A demonstration of the Redis database. 项目地址: https://gitcode.com/gh_mirrors/tr/try.redis 当你第一次听说Redis时,是否被那些晦涩的技术术语吓退࿱…...
2026上半年数据库系统工程师(软考)上午题回忆与解析(非标答版)
本文为考后回忆整理,非官方标准答案,旨在为考后对答案及下半年备考的同学提供参考。题目顺序和表述可能与原卷有出入,欢迎在评论区指正、补充。📊 整体考情分析 刚结束的2026年上半年数据库系统工程师考试,上午题的风格…...
长期使用Taotoken聚合服务对项目月度账单的可预测性提升
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 长期使用Taotoken聚合服务对项目月度账单的可预测性提升 在AI驱动的项目开发与运营中,成本控制与预算规划是团队管理者…...
基于ESP32的AIS转WiFi转换器:实现NMEA 0183数据无线传输
1. 项目概述:从VHF-AIS接收器到iPad的无线桥梁作为一名经常在海上折腾电子设备的航海爱好者,我最近遇到了一个挺实际的需求:我的主力导航设备是iPad上的iSailor应用,它功能强大、界面友好,但有个“硬伤”——它需要通过…...
如何进行TVA仿真引擎的“光照地狱”训练?
重磅预告:本专栏将独家连载系列丛书《智能体视觉技术与应用》部分精华内容,该书是世界首套系统阐述“因式智能体”视觉理论与实践的专著,特邀美国 TypeOne 公司首席科学家、斯坦福大学博士 Bohan 担任技术顾问。Bohan先生师从美国三院院士、“…...
2026年一键生成论文工具对比实测:5款神器从选题到格式全流程护航
写论文的焦虑,是每个科研人和学生都心照不宣的“隐形压力”。选题无从下手,文献检索耗时费力,逻辑框架反复推翻,格式排版让人抓狂,查重降重更是像在和系统玩“猫鼠游戏”。2026年的AI工具早已不是过去那种“打字机”&a…...
浏览器指纹识别机制深度剖析与反识别技术实现
一、浏览器指纹技术基础认知1.1 浏览器指纹的核心定义在数字化时代,每一台接入互联网的设备都会留下独特的数字标识,浏览器指纹便是其中最关键的识别凭证之一。浏览器指纹是网站通过 JavaScript 脚本、HTTP 请求头、硬件接口调用等多种技术手段ÿ…...
多模型聚合平台如何助力网站AIB测试与选型
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 多模型聚合平台如何助力网站AIB测试与选型 对于网站产品经理而言,首页文案的生成质量直接影响用户的第一印象和转化率。…...
通用物联网开发板设计:基于ESP8266的硬件集成与开发实践
1. 项目概述:为什么我们需要一块“通用”的物联网开发板?在捣鼓了几年物联网项目之后,我发现自己桌面上堆满了各种开发板:ESP8266、ESP32、Arduino Uno、STM32 Nucleo……每个项目都要重新连线、配置电源、焊接传感器接口…...
