Java Native Interface 四--JNI中引用类型
本文是《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中引用类型的更多相关文章
- Java Native Interface 二 JNI中对Java基本类型和引用类型的处理
本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 Java编程里会使用到两种类型:基本类型(如 ...
- Java Native Interface 六JNI中的异常
本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 在这里只讨论调用JNI方法可能会出现的异常, ...
- Java Native Interface Specification(JNI)
Java Native Interface Specification(JNI) 使用场景: 需要的功能,标准的java不能提供 有了一个用其他的语言写好的工具包,希望用java去访问它 当需要高性能 ...
- Java Native Interface 基于JNI的嵌入式手机软件开发实例
1.通过JNI和c/c++的库组件.其他代码交互 2.java和c不能互通的原因时数据类型问题 Introduction https://docs.oracle.com/javase/8/docs/t ...
- Java Native Interface 五 JNI里的多线程与JNI方法的注册
本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 JNI里的多线程 在本地方法里写有关多线程的 ...
- Java Native Interface(JNI)
JNI能让Java代码在Java虚拟机里调用其他编程语言(例如C.C++)写的应用或库,且不会影响任何Java虚拟机的实现. 什么时候用JNI? 1.应用程序所需的平台相关功能,标准的Java类库不支 ...
- 【详解】JNI (Java Native Interface) (二)
案例二:传递参数给C代码,并从其获取结果 注:这里传递的参数是基本类型的参数,在C代码中有直接的映射类型. 此案例所有生成的所有文件如下: (1)编写案例二的Java代码,如下: 这里我们定义了一个n ...
- +Java中的native关键字浅析(Java+Native+Interface)++
JNI是Java Native Interface的 缩写.从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的 ...
- Java Native Interface Specification Contents 翻译
https://docs.oracle.com/en/java/javase/12/docs/specs/jni/index.html Google翻译 第1章:简介 本章介绍Java Native ...
随机推荐
- javascript深入理解js闭包
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- 用js实现动画效果核心方式
为了做好导航菜单,有时候需要在菜单下拉的时候实现动画效果,所以这几天就研究了研究如何用js实现动画效果,实现动画核心要用到两个函数,一个是setTimeOut,另一个是setInterval. 下边我 ...
- [LeetCode] Find All Numbers Disappeared in an Array 找出数组中所有消失的数字
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and ot ...
- [LeetCode] Max Sum of Rectangle No Larger Than K 最大矩阵和不超过K
Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...
- 【机器学习Machine Learning】资料大全
昨天总结了深度学习的资料,今天把机器学习的资料也总结一下(友情提示:有些网站需要"科学上网"^_^) 推荐几本好书: 1.Pattern Recognition and Machi ...
- ios应用程序结构
MVC开发模式 什么是mvc,相信有一定开发经验的程序员都应该知道. M —— 模型,为程序提供数据 V —— 视图,为用户提供界面 C —— 控制器,用来控制程序视图,即上面的V 在ios程序中,一 ...
- AngularJS指令
1. AngularJS指令的特点: AngularJS通过被称为指令的新属性来扩展HTML,指令的前缀为ng-. AngularJS通过内置的指令来为应用添加功能. AngularJS允许你自定义指 ...
- 测试对于list的sort与sorted的效率
sorted from time import clock from random import randint start = clock() a = [randint(0,1000000) for ...
- iOS开发小技巧 -- tableView-section圆角边框解决方案
[iOS开发]tableView-section圆角边框解决方案 tableView圆角边框解决方案 iOS 7之前,图下圆角边框很容易设置 iOS 7之后,tableviewcell的风格不再是圆角 ...
- 使用Amoeba for mysql实现mysql读写分离
Amoeba主要在应用层访问MySQL的时候充当query 路由功能,专注 分布式数据库 proxy 开发.座落与Client.DB Server(s)之间.对客户端透明.具有负载均衡.高可用性.Qu ...