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


JNI支持将类实例和数组类型(如jobject,jclass,jstring,jarray)作为不透明的引用。本地代码不直接检查不透明指针的内容,而是通过使用JNI方法来得到一个指向数据结构的指针的不透明引用。也就是说JNI操作的内容都是引用,因此我们只需要知道在JNI中有哪些引用。JNI支持三种不透明的引用:本地引用、全局引用,弱全局引用。

 本地引用和全局引用有不同的生命周期,本地引用是自释放的,而全局和弱全局引用需要程序员主动释放掉,否则会一起存在于程序中。本地引用和全局引用的对象不会被垃圾回收器回收(也就是只要存在本地引用或全局引用,这个对象就被认为是活跃的),而弱全局引用允许引用对象被垃圾回收器回收。需要注意的是,引用并不是在所有的上下文中都是有效的,也就是引用是有生命周期的,比如,你不能在本地代码(JNI方法的实现代码)中使用完本地引用后,将这个引用通过return语句返回(本地引用在使用完后,已经结束了生命周期,系统中将不存在这个引用了)。

本地引用(Local References)

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

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

全局引用(Global References)

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

弱全局引用(Weak Global References)

弱全局引用与全局引用类似,也可以在线程间共享和多次调用本地方法时共享。但也有区别,首先全局引用是通过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. weblogic的集群与配置

    目录(?)[-] 1.Weblogic的集群 2.创建Weblogic集群前的规划 3.开始创建我们的Weblogic集群 1.1 创建集群的总控制端aminserver 2.2 创建集群中的节点my ...

  2. elasticsearch按照配置时遇到的一些坑 [Failed to load settings from [elasticsearch.yml]]

    这里整理几个空格引起的问题. 版本是elasticsearch-2.3.0 或者elasticsearch-rtf-master Exception in thread "main" ...

  3. C语言学习 第十次作业总结

    同学们终于学到最有意思的东西:指针了.有人说指针是C语言的灵魂.虽然有点夸大,但是事实的确是如此.很多的时候,使用指针,会让过程变得简洁和精巧.这个在以后同学们深入学习使用C语言进行编程的时候就可以理 ...

  4. 混合使用UITabBarController和UINavigationController

    混合使用这两个控件的好处是我们可以在NavigationBar添加更多的东西,如标题,按钮等.让用户能够获得更多的信息. UITabBarController的属性ViewControllers接受以 ...

  5. LVS原理详解

    一.集群简介 什么是集群 计算机集群简称集群是一种计算机系统,它通过一组松散集成的计算机软件和/或硬件连接起来高度紧密地协作完成计算工作.在某种意义上,他们可以被看作是一台计算机.集群系统中的单个计算 ...

  6. 【BZOJ 1494】【NOI 2007】生成树计数

    http://www.lydsy.com/JudgeOnline/problem.php?id=1494 这道题..因为k很小,而且我们只关心连续的k个节点的连通性,所以把连续的k个点轮廓线上的连通性 ...

  7. BZOJ1923: [Sdoi2010]外星千足虫

    传送门 高斯消元求解Xor方程. 这个方程很容易换成xor的方程.然后用高斯消元搞就行了. 用bitset实现这个非常方便. //BZOJ 1923 //by Cydiater //2016.11.3 ...

  8. 使用vlc进行二次开发做自己的播放器

    可参考: 使用vlc播放器做rtsp服务器 使用vlc播放器播放rtsp视频 web网页中使用vlc插件播放相机rtsp流视频 使用 https://github.com/ZeBobo5/Vlc.Do ...

  9. Spring特性--DI

    DI:Dependency Injection(依赖注入),通俗的讲就是一种通过xml配置文件,为交给sping容器的对象初始化参数.又称做控制反转:Inversion of Control(IoC) ...

  10. MySQL点滴

    1. 只安装Server和Workbench即可: 2. 安装时安装Windows服务,可以在“管理 > 服务”中开启关闭服务: 3. mysql -uroot -p1234 4. PHP Fa ...