Android JNI编程提高篇之一

PPF函数可视化生产可能性边界线(R语言) 假设产品A的生产函数为A = 2 * R1 + R2,产品B的生产函数为B = R1 + 2 * R2,其中A和B分别表示产品A和产品B的产量,R1和R2表示资源1和资源2的分配数量。首先,让我们定义两种产品:产品A和产品B,它们的生产分别需要不同的资源和技术。现在我们已经计算了每种分配比例下的产品A和产品B的产量,接下来我们可以绘制生产可能性边界线。运行完整的代码后,我们将得到一个图形,显示了生产可能性边界线,该线代表经济体在给定资源和技术条件下所能生产的所有产品组合。 阅读详情
Simon在拙文《 Android JNI开发入门之二 》中提到了,Android JNI开发的深入学习的一些资料和方法。最近Simon在学习《 Java Native Interface: Programmer’s Guide and Specification 》,在学习过程中发现在JNI规范中关于引用部分是最难理解的,恕Simon愚钝,看了两遍才对其思想略有理解,在此和大家分享我对JNI规范中引用部分的理解,如果有错误之处,希望能和各位网友一起探讨。

什么是JNI规范中对象引用

    在JNI编程中,Native代码不能对Java虚拟机中对象的内存分布有任何假设。因为Java虚拟机可以根据自己的策略定义自己对象的内存布局。这就要求JNI规范有如下要求:

1、如果要在Native代码中生成Java对象,则必须调用Java虚拟机的JNI接口来生成。 
2、对Java对象的操作也需要调用Java虚拟机的JNI接口来进行。 
3、在Native代码中,通过引用来访问Java对象。对象引用有Java虚拟机的JNI接口返回,比如:NewStringUTF函数,用utf8的字符串创建一个Java字符串对象,在Native代码中以jstring类型的引用来访问它。

    JNI规范中的引用和Java中应用有类比关系,大家可以相互对照。

JNI引用的分类

    JNI规范中定义了三种引用——局部引用(Local reference),全局引用(Global reference),弱全局引用(Weak global reference)。

    这算三种引用的生存期是不同的,全局引用和弱全局引用的生存期为创建之后,到程序员显示的释放他们。局部引用会被Java虚拟机在当前上下文(可以理解成Java程序调用Native代码的过程)结束之后自动释放。

    全局引用和局部引用将会迫使Java虚拟机不会垃圾回收其指向的对象。而弱全局引用指向的对象可以被Java虚拟机垃圾回收。

    每种引用都有自己的用途,比如当Native函数返回的时候,需要返回局部引用(和C语言的局部变量要区分开)。全局引用和弱全局引用在多线程之间共享其指向的对象等。

局部引用

    这里重点要强调一下局部引用的有效期,很多有C语言背景的程序员会认为当Native函数结束之后局部引用就无效了,和C语言的局部变量对应。实际上JNI中的局部引用和C语言中局部变量是不同的,他的有效期是当前Native函数被调用的上下文中。我理解的调用上下文,为Java虚拟机的调用流程。Native函数是被Java虚拟机调用的,Native函数执行完成之后,控制流程将继续返回给Java虚拟机。局部变量在Native函数中,由Native代码调用Java虚拟机的JNI接口创建,秉着谁创建谁销毁的原则(软件设计一个常用规则),当Native函数执行完成之后,如果局部引用没有被Native代码显示删除,那么局部引用在Java虚拟机中还是有效的。Java虚拟机来决定在什么时候来删除这个对象。这和C语言的局部变量概念是不同的。这也可以解释为什么Natvie函数能够以一个局部引用为返回值了。

    JNI编程中,局部引用是最常被用到的概念。比如:大部分JNI函数都返回一个局部引用,所以局部引用概念理解正确非常重要。

    局部引用在Native代码显示释放非常重要。你可能会问,既然Java虚拟机会自动释放局部变量为什么还需要我在Native代码中显示释放呢?原因有以下几点:

1、Java虚拟机默认为Native引用分配的局部引用数量是有限的,大部分的Java虚拟机实现默认分配16个局部引用。当然Java虚拟机也提供API(PushLocalFrame,EnsureLocalCapacity)让你申请更多的局部引用数量(Java虚拟机不保证你一定能申请到)。有限的资源当然要省着点用,否则将会被Java虚拟机无情抛弃(程序崩溃)。JNI编程中,实现Native代码时强烈建议调用PushLocalFrame,EnsureLocalCapacity来确保Java虚拟机为你准备好了局部变量空间。 
2、如果你实现的Native函数是工具函数,会被频繁的调用。如果你在Native函数中没有显示删除局部引用,那么每次调用该函数Java虚拟机都会创建一个新的局部引用,造成局部引用过多。尤其是该函数在Native代码中被频繁调用,代码的控制权没有交还给Java虚拟机,所以Java虚拟机根本没有机会释放这些局部变量。退一步讲,就算该函数直接返回给Java虚拟机,也不能保证没有问题,我们不能假设Native函数返回Java虚拟机之后,Java虚拟机马上就会回收Native函数中创建的局部引用,依赖于Java虚拟机实现。所以我们在实现Native函数时一定要记着删除不必要的局部引用,否则你的程序就有潜在的风险,不知道什么时候就会爆发。 
3、如果你Native函数根本就不返回。比如消息循环函数——死循环等待消息,处理消息。如果你不显示删除局部引用,很快将会造成Java虚拟机的局部引用内存溢出。

    在JNI中显示释放局部引用的函数为DeleteLocalRef,大家可以查看手册来了解调用方法。

    在JDK1.2中为了方便管理局部引用,引入了三个函数——EnsureLocalCapacity、PushLocalFrame、PopLocalFrame。这里介绍一下PushLocalFrame和PushLocalFrame函数。这两个函数是成对使用的,先调用PushLocalFrame,然后创建局部引用,并对其进行处理,最后调用PushLocalFrame释放局部引用,这时Java虚拟机也可以对其指向的对象进行垃圾回收。可以用C语言的栈来理解这对JNI API,调用PushLocalFrame之后Native代码创建的所有局部引用全部入栈,当调用PopLocalFrame之后,入栈的局部引用除了需要返回的局部引用(PushLocalFrame和PopLocalFrame这对函数可以返回一个局部引用给外部)之外,全部出栈,Java虚拟机这时可以释放他们指向的对象。具体的用法可以参考手册。这两个函数使JNI的局部引用由于和C语言的局部变量用法类似,所以强烈推荐使用。

    当创建局部变量之后,将迫使Java虚拟机不对其指向的对象进行垃圾回收,直到Native代码显示调用了DeleteLocalRef删除局部引用。Native代码调用DeleteLocalRef显示删除局部引用之后,Java虚拟机就可以对局部引用指向的对象垃圾回收了。当Native代码创建了局部引用,但未显示调用DeleteLocalRef删除局部引用,并返回Java虚拟机的话,那么由虚拟机来决定什么时候删除该局部引用,然后对其指向的对象垃圾回收。程序员不能对java虚拟机删除局部引用的时机进行假设。

    局部引用仅仅对于java虚拟机当前调用上下文有效,不能够在多次调用上下文中共享局部引用。这句话也可以这样理解:局部引用只对当前线程有效,多个线程之间不能共享局部引用。局部引用不能用C语言的静态变量或者全局变量来保存,否则第二次调用的时候,将会产生崩溃。。

    本文叙述了JNI规范中局部引用的理解,后续文章《Android JNI编程提高篇之二》我们将会继续关注全局变量和弱全局变量。

转自:http://blog.youkuaiyun.com/gemmem/article/details/7290048

SAP采购申请审批策略配置简介 SAP采购申请审批策略配置简介 1、CT04创建特征 阅读详情

相关推荐

TDISP(TEE Device Interface Security Protocol)软件操作流程

/ 1. SPDM会话相关定义(🔶1-37、🔶1-187)// SPDM会话ID// AES-256-GCM加密密钥(TDISP要求)// 初始向量// 会话是否激活// 2. IDE流配置(🔶1-52、🔶1-625)// IDE流ID// 4个子流的AES密钥(覆盖所有子流类型)// 密钥是否已配置// 3. TDI状态与配置(🔶1-207、🔶1-210)TDI_CONFIG_UNLOCKED = 0, // 初始配置态。

inquisiter 1429

JNI 本地引用和全局引用

1. 概述: 在JNI中 支持三种难懂的引用,分别是:本地引用(local references),全局引用( global references),弱全局引用(weak global references.)。 本地引用和全局引用有不同的生命周期,本地引用被自动释放,而全局引用和弱全局引用需要程序员来释放。本地引用和全局引用阻止被垃圾回收,另一方面,弱全局引用允许被垃圾回收不是所有的引用

Kuangjp的专栏 1852

华硕电脑Win10改Win7系统:BIOS设置详解

通过上述步骤,华硕电脑用户可以将系统从Windows 10更改为Windows 7。虽然这个过程可能涉及一些技术细节和潜在的风险(如数据丢失和驱动不兼容),但只要按照指南仔细操作并做好准备工作,大多数用户应该能够成功完成系统回滚。请记住,在进行任何系统更改之前都要备份重要数据,并确保已了解所有潜在的风险和限制。希望本文能够帮助到需要回滚到Windows 7的华硕电脑用户!

nntxthml的博客 2261

Android JNI开发详解(5)-引用篇

原文出处:http://www.ccbu.cc/index.php/android/android-jni-ref.html 在JNI规范中定义了三种引用:局部引用(Local Reference)、全局引用(Global Reference)、弱全局引用(Weak Global Reference)。 1. 局部引用 1.1 局部引用 通过NewLocalRef和各种JNI接口创建(FindClass、NewObject、GetObjectClass和NewCharArray等)。会阻止GC回收所引用的对

^_虫虫_^的专栏 485

QT播放器插件内嵌浏览器配合流媒体实现国标摄像头网页端播放

基本原理在浏览器⽹页中的指定播放窗口的位置和⼤⼩,实现⼀个内嵌到⽹页中显⽰的播放窗⼝,前端还必须可对这个内嵌播放窗⼝进⾏控制,⽽且播放窗⼝必须跟随浏览器窗⼝的移动和缩放、⽹页滚动、标签页切换、关闭等操作进⾏⾃动联动。播放器可以通过QT实现。这个播放窗⼝同时提供Web Socket的服务端和JSON打包命令的解析执⾏模块,前端就可以通过Web Socket连接后发送JSON打包的控制命令实现控制播放窗⼝。

cameravision的博客 562

论文超详细精读|万字:2s-AGCN

1. 提出了一种新的双流自适应图卷积网络(2S-AGCN)用于基于骨架的动作识别。**模型中的图的拓扑既可以统一地学习,也可以通过BP算法以端到端的方式单独学习。** 2. 提出了一种同时对**一阶和二阶信息(骨架的长度与方向)建模的双流框架**,在识别精度上有了显著的提高。 它将骨架数据的图结构参数化,并嵌入到网络中,与模型共同学习和更新。 3. 文章主要创新点有两个,一个是双流网络,另外一个是自适应。

IanYue的博客 6382

Android NDK开发(十一):JNI函数接口详解—引用

JNI中的引用与java中的类似,是用来在JNI中访问java对象的,那么JNI中谁来持有引用呢,那当然是引用变量,那么引用变量如何定义呢,那当然是通过JNI定义的引用类型。JNI中也定义了与java引用类型对应的引用类型(如:jobject、jstring、jclass、jarray、jintArray等),与java类似,JNI的这些引用类型定义的变量称为引用变量,用于持有相同类型的引用,进而访问Java对象。

u04160526 1546

企业微信/飞书/钉钉扫码连WiFi保姆级教程(附访客授权技巧)

本文提供了一份企业微信、飞书、钉钉扫码连接WiFi的实战部署教程。通过集成标准Radius协议与OAuth 2.0,企业可实现基于身份的无密码网络认证,并详细介绍了访客授权、权限分级等精细化管理技巧,有效提升无线网络的安全性与员工体验。

t4y5u6i7o的博客 1194

JNI技术规范 - 第四章 JNI函数(2)

目录 第一章 介绍第二章 设计机制第三章 JNI类型和数据结构第四章 JNI函数(1)第四章 JNI函数(2)第四章 JNI函数(3)第四章 JNI函数(4)第五章 Invocation API 第四章 JNI函数 4.5 全局和局部引用 局部引用只在本地方法执行的过程有有效。在本地方法返回时它们会被自动释放掉。所有的局部引用都有消耗一些Java虚拟机的资源。开发者必须确保本地方法不会过度...

The way I walk 548

计算蛋白质结构中氨基酸之间的方向和方位

方向 (Direction):通过相邻氨基酸的 CαCα​ 原子坐标差值,得到方向向量,描述两个氨基酸之间的几何方向。方位 (Orientation):可以通过二面角(如 Psi)来表示相邻氨基酸之间的旋转关系,或者通过局部坐标系(基于 NN、CαCα​、CC 原子)描述残基的空间取向。这些计算是研究蛋白质结构动力学、折叠过程、以及相互作用的基础,尤其是在使用机器学习和深度学习模型进行蛋白质结构预测时,这些几何信息有助于更好地捕捉残基之间的空间关系。

qq_27390023的博客 1679

基于分段线性近似的Softmax硬件加速器设计

本文深入探讨了基于分段线性近似的Softmax硬件加速器设计。针对深度学习模型中Softmax函数在硬件实现时指数运算成本高昂的问题,提出用分段线性拟合替代传统泰勒展开,通过一次乘加操作高效完成计算,并详细分析了输入范围压缩、精度与硬件资源权衡、以及包含地址生成、参数查找、乘加计算和归一化的完整硬件架构。该方法在保证精度的同时,显著提升了AI边缘芯片的推理速度和能效。

weixin_28278377的博客 312

Android JNI编程提高篇之二

上文《Android JNI编程提高篇之一》中我和大家分享了局部引用的一些理解,本文我将继续和大家全局引用和弱全局引用的一些理解。这也可以作为我学习《Java Native Interface: Programmer’s Guide and Specification》一个总结,欢迎大家对本文的理解拍砖。 全局引用 在所有引用中,我觉得全局引用是最好理解的一个了。为什么呢?主要

tubage技术点滴 501

OpenClaw人人养虾:接入即时通讯平台Zalo

通过 Zalo Official Account(OA,官方账号)API,可以将 OpenClaw 接入 Zalo,实现面向越南用户的自动化客服和互动。

王国平的博客 437
上一篇: Android JNI编程提高篇之二
下一篇: git使用
HabbyGe
博客等级 码龄16年 46粉丝 143原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值