• 【JNI知识三】引用Java对象


      原始类型,如整形、字符型等,都是可以在Java和本地代码之间进行复制的。另一方面,任意的Java对象都是通过引用进行传递的。虚拟机必须跟踪已传递给本地代码中的所有对象,以便于这些对象不被垃圾回收器释放。反过来,本地代码必须有一个方式通知虚拟机它不再需要这些对象。此外,垃圾收集器必须能够将本机代码引用的对象移除。

    全局和局部引用

      JNI将本地代码使用的对象引用分为两类:局部引用和全局引用。局部引用在本地方法的调用过程中是有效的,并在本地方法返回时自动释放。全局引用一直有效,直到他们被显式释放。

      对象被传递到本地方法并作为局部引用。JNI函数所返回的所有Java对象都是局部引用。JNI允许程序员从局部引用创建全局引用。期望Java对象的JNI函数可接受全局和局部引用。本地方法会返回局部或全局引用给VM作为结果。

      在大多数情况下,程序员应该依靠虚拟机在本地方法返回后释放所有的局部引用。不过,有些时候程序员也应该显式释放局部引用。考虑一下,比如,在以下情况下:

    • 本地方法访问一个大型Java对象,从而创建了一个该Java对象的本地引用。然后,本地方法执行额外的计算,然后再返回给调用者。大型Java对象的局部引用会防止对象被垃圾回收,即使该对象在剩余部分运算中不再被使用。
    • 本地方法创建了大量的局部引用,虽然他们中的所有并不是在同一时间被使用。由于虚拟机需要一定的空间来保存一个本地引用,创建太多的局部引用可能会导致系统运行内存溢出。例如,一个本地方法遍历一个大的对象数组,获取元素作为局部引用,并在每次迭代中操作一个元素。每次迭代之后,程序员就不再需要这些数组元素的本地引用。

      在本地方法内部,JNI允许程序员在任何时候手动删除本地引用。为了确保程序员可以手动释放局部引用,JNI函数不被允许创建额外的局部引用,它们作为结果返回的引用除外。

      局部引用仅在他们被创建的线程中是有效的。本地代码不能传递本地引用从一个线程到另一个线程。

    实现局部引用

      为了实现局部引用,Java虚拟机为每个从Java到本地方法的控制权的转移创建了一个注册表。注册表映射了Java对象的不可移动的本地引用,并保持对象不被垃圾回收。所有传递给本地方法的Java对象(包括那些作为JNI函数的调用结果被返回的)都会被自动添加到注册表中。在本地方法返回后注册表将会被删除,使所有记录可以被垃圾回收

      有不同的方法来实现注册表,如使用表,链表,或哈希表。虽然可使用引用计数,以避免在注册表中重复的项目,JNI的实现不一定必须要检测和合并重复的条目。

      注意,局部变量通过谨慎地扫描本地栈不能被如实地实现,本机代码可以存储局部引用到全局或堆数据结构。

     

  • 相关阅读:
    1553: Good subsequence (很奇妙的set模拟题,也可以直接暴力)
    1550: Simple String (做得少的思维题,两个字符串能否组成另外一个字符串问题)
    1549: Navigition Problem (几何计算+模拟 细节较多)
    1548: Design road (思维题 做法:三分找极值)
    Python 正则表达式入门(初级篇)
    Python中的正则表达式教程
    软件自动化测试的学习步骤
    自动化测试的Selenium的python版安装与使用
    自动化测试一些问题
    自动化测试
  • 原文地址:https://www.cnblogs.com/wzfyang/p/2654765.html
Copyright © 2020-2023  润新知