本文是《The Java Native Interface Programmer’s Guide and Specification》读书笔记


  1. JNI支持将类实例和数组类型(如jobject,jclass,jstring,jarray)作为不透明的引用。本地代码不直接检查不透明指针的内容,而是通过使用JNI方法来得到一个指向数据结构的指针的不透明引用。也就是说JNI操作的内容都是引用,因此我们只需要知道在JNI中有哪些引用。JNI支持三种不透明的引用:本地引用、全局引用,弱全局引用。
  2. 本地引用和全局引用有不同的生命周期,本地引用是自释放的,而全局和弱全局引用需要程序员主动释放掉,否则会一起存在于程序中。本地引用和全局引用的对象不会被垃圾回收器回收(也就是只要存在本地引用或全局引用,这个对象就被认为是活跃的),而弱全局引用允许引用对象被垃圾回收器回收。需要注意的是,引用并不是在所有的上下文中都是有效的,也就是引用是有生命周期的,比如,你不能在本地代码(JNI方法的实现代码)中使用完本地引用后,将这个引用通过return语句返回(本地引用在使用完后,已经结束了生命周期,系统中将不存在这个引用了)。

本地引用(Local References)

大部分的JNI方法(函数)都会创建本地引用,比如,通过JNI方法NewObject创建一个新的实例,并返回这个实例的引用。我们在本地方法里不能通过静态变量来保存一个本地引用。下面是一个错误的例子。

  1. jstring
  2. MyNewString(JNIEnv *env, jchar *chars, jint len)
  3. {
  4. //试图通过一个静态变量来保存本地引用
  5. static jclass stringClass = NULL;
  6. jmethodID cid;
  7. ....
  8. //判断本地引用是否为空
  9. if (stringClass == NULL) {
  10. stringClass = (*env)->FindClass(env,
  11. "java/lang/String");
  12. if (stringClass == NULL) {
  13. return NULL; /* exception thrown */
  14. }
  15. }
  16. /* 这里就会发生错误,因为stringClass指向的对象可能不存在了*/
  17. cid = (*env)->GetMethodID(env, stringClass ,
  18. "<init>", "([C)V");
  19. ....
  20. }
  1. 上面的代码中,试图通过一个静态变量来保存本地引用,这也许可以减小重复调用`FindClass`方法的开销,这个方法在第一次调用时不会出错,可以正常执行。但当第二次调用这个方法时,就会出错了。因为本地引用在这个本地方法执行完后就自动释放了,虽然stringClass保存了上一次执行的引用,但它指向的那个对象可能由于没有任何引用,被垃圾回收器回收了,所以在第二次执行时,试图去找到一个并不存在的对象,肯定是会出错的。并且本地引用只存在于创建时所在的线程,不能在其他线程中使用。因此不能通过试图将本地引用保存在全局变量中,以便在其他线程中使用。

全局引用(Global References)

  1. 我们可以通过全局引用来保存调用本地方法的某些结果,以便在下次调用时使用。同样的,全局引用可以在多个线程中使用(不局限于创建时所在的线程),并且在程序员主动释放前,都会一直有效。可以通过下面的代码来创建一个全局引用:
  1. /* This code is OK */
  2. jstring
  3. MyNewString(JNIEnv *env, jchar *chars, jint len)
  4. {
  5. static jclass stringClass = NULL;
  6. ...
  7. if (stringClass == NULL) {
  8. jclass localRefCls =
  9. (*env)->FindClass(env, "java/lang/String");
  10. if (localRefCls == NULL) {
  11. return NULL; /* exception thrown */
  12. }
  13. /* 用一个本地引用参数来创建一个全局引用 */
  14. stringClass = (*env)->NewGlobalRef(env, localRefCls);
  15. /* 释放掉本地引用 */
  16. (*env)->DeleteLocalRef(env, localRefCls);
  17. /* 判断全局引用是否创建成功 */
  18. if (stringClass == NULL) {
  19. return NULL; /* out of memory exception thrown */
  20. }
  21. }
  22. ...
  23. }

弱全局引用(Weak Global References)

  1. 弱全局引用与全局引用类似,也可以在线程间共享和多次调用本地方法时共享。但也有区别,首先全局引用是通过JNI方法`NewGlobalRef`创建的,而弱全局引用是通过JNI方法`NewGlobalWeakRef`,并通过JNI方法`DeleteGlobalWeakRef`释放;其次弱全局引用并不会保证所引用的对象不会被垃圾回收器回收。因此我们在使用弱全局引用时,需要检查引用所反射的对象是否还存活。

杂谈

给定两个本地,全局或弱全局引用,我们可以通过JNI方法1isSameObject来判断这两个引用是不是指向同一个对象。返回JNI_TRUE,JNI_FALSE,NULL分别表示指向同一个对象,不是指向同一个对象,指向一个空对象。

Java里的引用类型

Java里一共有四种引用类型(摘录自以前的笔记,但不知道是从哪里看到的的):

  • 强引用,在代码中普遍存在,类似于Object object=new Object()这类的引用,只要强引用不存在,则GC永远不会回收掉引用的对象;
  • 软引用,用来描述一些有用但非必须的对象。对于软引用关联着的对象,在系统将在发生内存溢出时,将会把这些对象列入回收范围之中进行二次回收,如果这次还没有回收到足够的内存,才会抛出内存溢出异常。在JDK1.2后,提供了SofeReference来建立软引用;
  • 弱引用,也用来描述非必须对象,但强度比弱引用更弱一些,被弱引用关联的对象只能存活到下一次GC发生之前,当GC工作时,无论当时内存是否足够,都会被回收,可以用WeakReference来建立弱引用。
  • 虚引用,虚引用也叫幻影引用,这是最弱的一种引用,一个对象是否虚引用都不会对其生存时构成影响,也不能通过虚引用来取得一个对象实例。为一个对象设置虚引用的目的就是在这个对象被回收时收到一个通知,可以通过PhantomReference来建立虚引用。

Java Native Interface 四--JNI中引用类型的更多相关文章

  1. Java Native Interface 二 JNI中对Java基本类型和引用类型的处理

    本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 Java编程里会使用到两种类型:基本类型(如 ...

  2. Java Native Interface 六JNI中的异常

    本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 在这里只讨论调用JNI方法可能会出现的异常, ...

  3. Java Native Interface Specification(JNI)

    Java Native Interface Specification(JNI) 使用场景: 需要的功能,标准的java不能提供 有了一个用其他的语言写好的工具包,希望用java去访问它 当需要高性能 ...

  4. Java Native Interface 基于JNI的嵌入式手机软件开发实例

    1.通过JNI和c/c++的库组件.其他代码交互 2.java和c不能互通的原因时数据类型问题 Introduction https://docs.oracle.com/javase/8/docs/t ...

  5. Java Native Interface 五 JNI里的多线程与JNI方法的注册

    本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 JNI里的多线程 在本地方法里写有关多线程的 ...

  6. Java Native Interface(JNI)

    JNI能让Java代码在Java虚拟机里调用其他编程语言(例如C.C++)写的应用或库,且不会影响任何Java虚拟机的实现. 什么时候用JNI? 1.应用程序所需的平台相关功能,标准的Java类库不支 ...

  7. 【详解】JNI (Java Native Interface) (二)

    案例二:传递参数给C代码,并从其获取结果 注:这里传递的参数是基本类型的参数,在C代码中有直接的映射类型. 此案例所有生成的所有文件如下: (1)编写案例二的Java代码,如下: 这里我们定义了一个n ...

  8. +Java中的native关键字浅析(Java+Native+Interface)++

    JNI是Java Native Interface的 缩写.从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的 ...

  9. Java Native Interface Specification Contents 翻译

    https://docs.oracle.com/en/java/javase/12/docs/specs/jni/index.html Google翻译 第1章:简介 本章介绍Java Native ...

随机推荐

  1. mac上设置新版chrome浏览器跨域

    设置方法 打开一个新的可跨域的chrome窗口实现方法: 1. 打开终端 2. 输入下面的命令( 需要替换路径中的yourname ) open -n /Applications/Google\ Ch ...

  2. [LeetCode] Word Search II 词语搜索之二

    Given a 2D board and a list of words from the dictionary, find all words in the board. Each word mus ...

  3. DrawerLayout 和 NavigationView 的使用

    参考: 1.NavigationView 的使用 2.NavigationView更改菜单icon和title颜色变化效果 3.Android 自己实现 NavigationView 转了第一篇   ...

  4. 关于javascript的运动教程

    一.javascript的匀速运动 关于物体的javascript匀速运动要点分析: 1.物体关于运动的时候,我们要打开定时器 2.打开定时器的时候我们记得要在停止的时候关闭定时器,同时应该注意的是一 ...

  5. thusc2016游记&&滚粗记&&酱油记

    #include <cstdio> using namespace std; int main(){ puts("转载请注明出处:http://www.cnblogs.com/w ...

  6. Socket编程实践(3) 多连接服务器实现与简单P2P聊天程序例程

    SO_REUSEADDR选项 在上一篇文章的最后我们贴出了一个简单的C/S通信的例程.在该例程序中,使用"Ctrl+c"结束通信后,服务器是无法立即重启的,如果尝试重启服务器,将被 ...

  7. win7搭建双系统ubuntu

    参考链接:http://www.linuxidc.com/Linux/2014-10/108430.htm 0.下载EasyBCD软件和ubuntu镜像1.在win7,右键我的电脑,磁盘管理,压缩卷, ...

  8. bzoj 4326: NOIP2015 运输计划

    4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个 ...

  9. CSS之列表标签

    1 无序列表 无序列表,用来表示一个列表的语义,并且每个项目和每个项目之间,是不分先后的. ul就是英语unordered list,"无序列表"的意思. li 就是英语list ...

  10. .vue文件里引用单独样式和js文件

    style只能引一个,script可以引多个