APENFT基金会有销毁回收机制吗

当前位置:首页 > 币圈百科 > APENFT基金会有销毁回收机制吗

APENFT基金会有销毁回收机制吗

2022-04-14币圈百科118

线程执行完会自动销毁吗

一般来说会的,因为java有自动的回收机制·····目测执行完毕线程不会自动销毁建议在子程序末端添加一掉关闭线程的命令

APENFT基金会有销毁回收机制吗

怎么回收jni中的global

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

这算三种引用的生存期是不同的。

全局引用的生存期为创建之后,直到程序员显式的释放它。

局部引用的生存期为创建后,直到程序员显式的释放他们,或在当前上下文(可以理解成Java程序调用Native代码的过程)结束之后没有被JVM发现有JAVA层引用而被JVM回收并释放。

弱全局引用的生存期为创建之后,到程序员显式的释放他们或JVM认为应该回收它的时候(比如内存紧张的时候)进行回收而被释放。

二、局部引用

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

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

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

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

三、全局引用

在所有引用中,我觉得全局引用是最好理解的一个了。为什么呢?主要和C语言的全局变量非常相近。

我已经提到局部引用大部分是通过JNI API返回而创建的,而全局引用必须要在Native代码中显示的调用JNI API NewGlobalRef来创建,创建之后将一直有效,直到显示的调用DeleteGlobalRef来删除这个全局引用。请注意NewGlobalRef的第二个参数,既可以用一个局部引用,也可以用全局引用生成一个全局引用,当然也可以用弱全局引用生成一个全局引用,但是这中情况有特殊的用途,后文会介绍。

全局引用和局部引用一样,可以防止其指向的对象被Java虚拟机垃圾回收。与局部引用只在当前线程有效不同的是全局引用可以在多线程之间共享(如果是多线程编程需要注意同步问题)。

四、弱全局引用

弱全局引用和全局引用一样,可以在多个线程之间共享,但是并不强制进行显式的销毁。虽然在我们确定不再需要弱全局引用的时候,建议进行显式的销毁(调用DeleteWeakGlobalRef)。但是即使我们不显式的销毁弱全局引用,JAVA虚拟机也能在它认为必要的时候自动回收并销毁弱全局引用。创建弱全局引用请使用NewWeakGlobalRef,显式销毁弱全局引用请使用DeleteWeakGlobalRef。

与全局引用和局部引用能够阻止Java虚拟机垃圾回收其指向的对象不同,弱全局引用指向的对象随时都可以被Java虚拟机垃圾回收,所以使用弱全局变量的时候,要时刻记着:它所指向的对象可能已经被垃圾回收了。JNI API提供了引用比较函数IsSameObject,用弱全局引用和NULL进行比较,如果返回JNI_TRUE,则说明弱全局引用指向的对象已经被释放。需要重新初始化弱全局引用。根据上面的介绍你可能会写出如下的代码:

static jobject weak_global_ref = NULL;

if((*env)->IsSameObject(env, weak_global_ref, NULL) == JNI_TRUE)

/* Init week global referrence again */

weak_global_ref = NewWeakGlobalRef(...);

/* Process weak_global_ref */

上面这段代码表面上没有什么错误,但是我们忘了一点儿,Java虚拟机的垃圾回收随时都可能发生。假设如下情形:

1、通过引用比较函数IsSameObject判断弱全局引用是否有效的时候,返回JNI_FALSE,证明其指向对象有效。

2、这时Java虚拟机进行了垃圾回收,回收了弱全局引用指向的对象。

3、这样如果我们后面访问弱全局引用指向的对象,将会引发程序崩溃,因为弱全局引用指向对象已经被Java虚拟机回收了。

根据JNI标准手册《Weak Global References》中的介绍,我们可以有这样一个使用弱全局引用的方案。在使用全局引用之前,我们先通过NewLocalRef函数创建一个局部引用,然后使用这个局部引用来访问该对象进行处理,当完成处理之后,删除局部引用。局部引用可以阻止Java虚拟机回收其指向的对象,这样可以保证在处理期间弱全局引用和局部引用指向的对象不会被Java虚拟机回收。假如弱全局引用指向对象已经被Java虚拟机回收,则NewLocalRef函数将会返回NULL,则创建局部引用失败,这个返回值有助于我们判断是否需要重新初始化弱全局引用。我们可以写出如下的代码:

static jobject weak_global_ref = NULL;

jobject local_ref;

/* We ensure create local_ref success */

while ( week_global_ref == NULL

|| (local_ref = NewLocalRef(env, weak_global_ref)) == NULL )

/* Init week global referrence again */

weak_global_ref = NewWeakGlobalRef(...);

/* Process local_ref */

.....

(*env)->DeleteLocalRef(env, local_ref);

注意在《Java Native Interface: Programmer’s Guide and Specification》的例子中,有很多不是按照如上的代码实现的,那些代码是有潜在风险的,请各位朋友注意。

弱全局引用是可以用来缓存jclass对象,但是用全局引用来缓存jclass对象将非常的危险。这里需要简单介绍一下Native的共享库的卸载。当Class Loader释放完所有的class后,然后Class Loader会卸载Native的共享库。如果我们用全局引用来缓存jclass对象的话,根据前面对全局引用对Java虚拟机垃圾回收机制的影响,将会阻止Java虚拟机回收该对象。如果我们不显式的释放全局引用(通过DeleteGlobalRef),则Class Loader也将不能释放这个jclass对象,进而造成Class Loader不能卸载Native的共享库(永远无法释放)。如果用弱全局引用来缓存将不会有这个问题,Java虚拟机随时都可以释放它指向的对象。

至此我们把JNI规范中的三种引用都进行了一个简单的介绍,在此我对以上内容做一个简单总结:

1、局部引用是Native代码中最常用的引用。大部分局部引用都是通过JNI API返回来创建,也可以通过调用NewLocalRef来创建。另外强烈建议Native函数返回值为局部引用。局部引用只在当前调用上下文中有效,所以局部引用不能用Native代码中的静态变量和全局变量来保存。另外时刻要记着Java虚拟机局部引用的个数是有限的,编程的时候强烈建议调用EnsureLocalCapacity,PushLocalFrame和PopLocalFrame来确保Native代码能够获得足够的局部引用数量。

2、全局变量必须要通过NewGlobalRef创建,通过DeleteGlobalRef删除。主要用来缓存Field ID和Method ID。全局引用可以在多线程之间共享其指向的对象。在C语言中以静态变量和全局变量来保存。

3、全局引用和局部引用可以阻止Java虚拟机回收其指向的对象。

4、弱全局引用必须要通过NewWeakGlobalRef创建,通过DeleteWeakGlobalRef销毁。可以在多线程之间共享其指向的对象。在C语言中通过静态变量和全局变量来保持弱全局引用。弱全局引用指向的对象随时都可能会被Java虚拟机回收,所以使用的时候需要时刻注意检查其有效性。弱全局引用经常用来缓存jclass对象。

5、全局引用和弱全局引用可以在多线程中共享其指向对象,但是在多线程编程中需要注意多线程同步。强烈建议在JNI_OnLoad初始化全局引用和弱全局引用,然后在多线程中进行读全局引用和弱全局引用,这样不需要对全局引用和弱全局引用同步(只有读操作不会出现不一致情况)。

蓑衣网-以上内容来自网络整理,不能代表本站立场,转载请注明出处。

本文链接:https://www.baoguzi.com/4403.html

APENFT基金会有销毁回收机制吗 | 分享给朋友:

相关文章

pe塑料_pe塑料是什么材料做的

pe塑料_pe塑料是什么材料做的

【pe塑料】聚乙烯和聚丙烯原料生产工艺相似,产品可用于制作塑料薄膜、注塑制品【pe塑料】、塑料管等。在许多情况下,这两种原料在性质和用途上有很大的相似之处。但实际上【pe塑料】,聚丙烯原料和聚乙烯原料...

比特币如何购买,普通人怎么购买比特币

比特币如何购买,普通人怎么购买比特币

【比特币如何购买,普通人怎么购买比特币】从比特币成为最具价值的加密货币资产那一刻,全球就有不少投资开始看好比特币,那么作为一个普通人能不能投资比特币呢,下面就跟随中本聪超市网小编一起了解【比特币如何购...

比特币客户端中文版,比特币软件下载安装

比特币客户端中文版,比特币软件下载安装

中国比特币交易平台排名小编推荐阅读“比特币客户端中文版,比特币软件下载安装”,比特币客户端顾名思义是能通过此软件进行比特币交易管理,那么怎么下载中文版呢,下面跟随中本聪超市网小...

APENFT官网(apeNFT币)

APENFT官网(apeNFT币)

APENFT上币安了吗 APENFT没上币安。 据官方最新消息,波场TRON创始人兼BitTorrent,CEO孙宇晨通过其社交媒体账号表示:网传APENFT在币安NFT自成交是不属实的,原因为另...

网上购买比特币被骗:网站上买比特币被骗几十万怎么办

网上购买比特币被骗:网站上买比特币被骗几十万怎么办

网上购买比特币被骗:网站上买比特币被骗几十万怎么办,新人在投资比特币过程中难免会遇到一些被骗行为,那么当网友在买比特币被骗后该怎么处理才正确呢,下面就跟随中本聪超市网小编一起了解网上购买比特币被骗:网...

马云购买200亿比特币(这是不是比特币投资者炒作)

马云购买200亿比特币(这是不是比特币投资者炒作)

马云购买200亿比特币(这是不是比特币投资者炒作) 最近看到网上都在疯传马云购买200亿比特币,其实这个问题小编自己也很感兴趣,那么马云购买200亿比特币是不是真...

2022比特币怎么交易买卖比特币在哪里买

2022比特币怎么交易买卖比特币在哪里买

比特币怎么交易买卖比特币在哪里买 比特币怎么交易买卖比特币在哪里买,不少新人想要购买比特币但是却苦于不知道怎么交易,当前交易比特币通常以比特币交易平台为主,下面蓑...

潮流兔NFT(潮流兔NFT)

潮流兔NFT(潮流兔NFT)

韩流兔男鞋品牌文化? 韩流图那些品牌很好,他代表了韩国的一些具有象征性的文化在这里做些,他有一定的意义,没折住寒流透男鞋品牌值得他的质量好,价钱合理,买的放心,穿的舒服。这个品牌是很有名的,我都听说...

狗狗币未来的升值空间,2022年狗狗币最新消息!

狗狗币未来的升值空间,2022年狗狗币最新消息!

狗狗币未来的升值空间,2022年狗狗币最新消息! 狗狗币未来的升值空间怎么样?其实到现在狗狗币可以说关注的人非常的多,并且有相当大的一部分...

【盐酸林可霉素】盐酸林可霉素滴眼液的作用与功效

【盐酸林可霉素】盐酸林可霉素滴眼液的作用与功效

【盐酸林可霉素】没关系。几天后就会消失。林可霉素有这样的副作用。【盐酸林可霉素】用太痛的热毛巾加热可以缓解肌肉注射。成人每天0.6~1.2g,儿童每天体重10~20mg/kg,分注。静脉点滴:一般成人...

【苄星青霉素的功效与作用】苄星青霉素皮试配方法

【苄星青霉素的功效与作用】苄星青霉素皮试配方法

【苄星青霉素的功效与作用】[概述]苄星青霉素,又称注射用苄星青霉素和长效青霉素,【苄星青霉素的功效与作用】是由二苄基乙二胺盐与悬浮液和缓冲液混合而成的白色结晶粉末;苄星青霉素能抑制细菌细胞壁的合成,进...

比特币减半什么意思,比特币为什么减半

比特币减半什么意思,比特币为什么减半

比特币减半什么意思,比特币为什么减半,不少网友应该都看到过关于比特币减半的提问,既然说好的比特币一共是2100万枚的,为什么会有什么减半你的,那么比特币减半到底是什么原因呢,下面就跟随中本聪超市网小编...

2022HQX币值多少人民币,有什么价值HQX币价格、上线100个交易平台

2022HQX币值多少人民币,有什么价值HQX币价格、上线100个交易平台

HOQU(简称HQX)是在以太坊平台上发行的加密货币令牌。HX货币今天的价格是0.00209771美元,24小时交易量是25305美元。在过去的24小时内,价格下跌了-1.6%。其流通供应量为1.8亿...

比特币期货合约交易规则(2022合约交易都有哪些规则)

比特币期货合约交易规则(2022合约交易都有哪些规则)

比特币期货合约交易规则(合约交易都有哪些规则) 比特币期货合约交易规则,对于接触个股票的朋友应该对期货一点不陌生,而比特币期货就是借鉴了金融市场期货的投资方式,下...

比特币矿机一天赚多少钱,一台矿机挖矿比特币一天能赚多少

比特币矿机一天赚多少钱,一台矿机挖矿比特币一天能赚多少

比特币矿机一天赚多少钱,一台矿机挖矿比特币一天能赚多少,比特币挖矿可能是不少网友的梦想,想着一枚比特币价值几十万的情况下是不是也能使用自己的电脑挖矿比特币呢,下面就跟随蓑衣网小编一起了解比特币矿机一天...