没有合适的资源?快使用搜索试试~ 我知道了~
JNI完全手册
需积分: 9 6 下载量 9 浏览量
2012-12-11
08:41:16
上传
评论
收藏 446KB DOC 举报
温馨提示
试读
64页
比较全面的介绍了JNI技术及其API接口,适合初学者。
资源推荐
资源详情
资源评论
1 - 简介
本章介绍 Java
本地接口
(Java Native Interface,JNI)。JNI 是本地编程接口。
它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语言(如
C、C++ 和汇编语言)编写的应用程序和库进行互操作。
JNI 最重要的好处是它没有对底层 Java 虚拟机的实现施加任何限制。因此,
Java 虚拟机厂商可以在不影响虚拟机其它部分的情况下添加对 JNI 的支持。程
序员只需编写一种版本的本地应用程序或库,就能够与所有支持 JNI 的 Java 虚
拟机协同工作。
本章论及以下主题:
Java
本地接口概述
背景
目标
Java
本地接口方法
利用
JNI
编程
JDK 1.1.2
中的变化
Java 本地接口概述
尽管可以完全用 Java 编写应用程序,但是有时单独用 Java 不能满足应用程序的
需要。程序员使用 JNI 来编写 Java
本地方法
,可以处理那些不能完全用 Java 编
写应用程序的情况。
以下示例说明了何时需要使用 Java 本地方法:
标准 Java 类库不支持与平台相关的应用程序所需的功能。
已经拥有了一个用另一种语言编写的库,而又希望通过 JNI 使 Java 代码
能够访问该库。
想用低级语言(如汇编语言)实现一小段时限代码。
通过用 JNI 编程,可以将本地方法用于:
创建、检查及更新 Java 对象(包括数组和字符串)。
调用 Java 方法。
捕捉和抛出异常。
加载类和获得类信息。
执行运行时类型检查。
也可以与
调用
API 一起使用 JNI,以允许任意本地应用程序嵌入到 Java 虚拟机
中。这样使得程序员能够轻易地让已有应用程序支持 Java,而不必与虚拟机源
代码相链接。
背景
目前,不同厂商的虚拟机提供了不同的本地方法接口。这些不同的接口使程序
员不得不在给定平台上编写、维护和分发多种版本的本地方法库。
下面简要分析一下部分已有本地方法接口,例如:
JDK 1.0 本地方法接口
Netscape 的 Java 运行时接口
Microsoft 的原始本地接口和 Java/COM 接口
JDK 1.0 本地方法接口
JDK 1.0 附带有本地方法接口。遗憾的是,有两点原因使得该接口不适合于其它
Java 虚拟机。
第一,平台相关代码将 Java 对象中的域作为 C 结构的成员来进行访问。但是,
Java
语言规范
没有规定在内存中对象是如何布局的。如果 Java 虚拟机在内存中
布局对象的方式有所不同,程序员就不得不重新编译本地方法库。
第二,JDK 1.0 的本地方法接口依赖于保守的垃圾收集器。例如,无限制地使用
unhand 宏使得有必要以保守方式扫描本地堆栈。
Java 运行时接口
Netscape 建议使用 Java 运行时接口 (JRI),它是 Java 虚拟机所提供服务的通用
接口。JRI 的设计融入了可移植性---它几乎没有对底层 Java 虚拟机的实现细节
作任何假设。JRI 提出了各种各样的问题,包括本地方法、调试、反射、嵌入
(调用)等等。
原始本地接口和 Java/COM 接口
Microsoft Java 虚拟机支持两种本地方法接口。在低一级,它提供了高效的原始
本地接口 (RNI)。RNI 提供了与 JDK 本地方法接口有高度源代码级的向后兼容
性,尽管它们之间还有一个主要区别,即平台相关代码必须用 RNI 函数来与垃
圾收集器进行显式的交互,而不是依赖于保守的垃圾收集。
在高一级,Microsoft 的 Java/COM 接口为 Java 虚拟机提供了与语言无关的标准
二进制接口。Java 代码可以象使用 Java 对象一样来使用 COM 对象。Java 类也
可以作为 COM 类显示给系统的其余部分。
目标
我们认为统一的,经过细致考虑的标准接口能够向每个用户提供以下好处:
每个虚拟机厂商都可以支持更多的平台相关代码。
工具构造器不必维护不同的本地方法接口。
应用程序设计人员可以只编写一种版本的平台相关代码就能够在不同的
虚拟机上运行。
获得标准本地方法接口的最佳途径是联合所有对 Java 虚拟机有兴趣的当事方。
因此,我们在 Java 获得许可方之间组织了一系列研讨会,对设计统一的本地方
法接口进行了讨论。从研讨会可以明确地看出标准本地方法接口必须满足以下
要求:
二进制兼容性 - 主要的目标是在给定平台上的所有 Java 虚拟机实现之间
实现本地方法库的二进制兼容性。对于给定平台,程序员只需要维护一
种版本的本地方法库。
效率 - 若要支持时限代码,本地方法接口必须增加一点系统开销。所有
已知的用于确保虚拟机无关性(因而具有二进制兼容性)的技术都会占
用一定的系统开销。我们必须在效率与虚拟机无关性之间进行某种折衷。
功能 - 接口必须显示足够的 Java 虚拟机内部情况以使本地方法能够完成
有用的任务。
Java 本地接口方法
我们希望采用一种已有的方法作为标准接口,因为这样程序员(程序员不得不
学习在不同虚拟机中的多种接口)的工作负担最轻。遗憾的是,已有解决方案
中没有任何方案能够完全地满足我们的目标。
Netscape 的 JRI 最接近于我们所设想的可移植本地方法接口,因而我们采用它
作为设计起点。熟悉 JRI 的读者将会注意到在 API 命名规则、方法和域 ID 的使
用、局部和全局引用的使用,等等中的相似点。虽然我们进行了最大的努力,
但是 JNI 并不具有对 JRI 的二进制兼容性,不过虚拟机既可以支持 JRI,又可以
支持 JNI。
Microsoft 的 RNI 是对 JDK 1.0 的改进,因为它可以解决使用非保守的垃圾收集
器的本地方法的问题。然而,RNI 不适合用作与虚拟机无关的本地方法接口。
与 JDK 类似,RNI 本地方法将 Java 对象作为 C 结构来访问。这将导致两个问
题:
RNI 将内部 Java 对象的布局暴露给了平台相关代码。
将 Java 对象作为 C 结构直接进行访问使得不可能有效地加入“写屏障”,
写屏障是高级的垃圾收集算法所必需的。
作为二进制标准,COM 确保了不同虚拟机之间的完全二进制兼容性。调用
COM 方法只要求间接调用,而这几乎不会占用系统开销。另外,COM 对象对
动态链接库解决版本问题的方式也有很大的改进。
然而,有几个因素阻碍了将 COM 用作标准 Java 本地方法接口:
第一,Java/COM 接口缺少某些必需功能,例如访问私有域和抛出普通异
常。
第二,Java/COM 接口自动为 Java 对象提供标准的 IUnknown 和
IDispatch COM 接口,因而平台相关代码能够访问公有方法和域。遗憾
的是,IDispatch 接口不能处理重载的 Java 方法,而且在匹配方法名称时
不区别大小写。另外,通过 IDispatch 接口暴露的所有 Java 方法被打包
在一起来执行动态类型检查和强制转换。这是因为 IDispatch 接口的设计
只考虑到了弱类型的语言(例如 Basic)。
第三,COM 允许软件组件(包括完全成熟的应用程序)一起工作,而不
是处理单个低层函数。我们认为将所有 Java 类或低层本地方法都当作软
件组件是不恰当的。
第四,在 UNIX 平台上由于缺少对 COM 的支持,所以阻碍了直接采用
COM。
虽然我们没有将 Java 对象作为 COM 对象暴露给平台相关代码,但是 JNI 接口
自身与 COM 具有二进制兼容性。我们采用与 COM 一样的跳转表和调用约定。
这意味着,一旦具有对
COM
的跨平台支持,
JNI
就能成为
Java
虚拟机的
COM
接口。
我们认为 JNI 不应该是给定 Java 虚拟机所支持的唯一的本地方法接口。标准接
口的好处在于程序员可以将自己的平台相关代码库加载到不同的 Java 虚拟机上。
在某些情况下,程序员可能不得不使用低层且与虚拟机有关的接口来获得较高
的效率。但在其它情况下,程序员可能使用高层接口来建立软件组件。实际上,
我们希望随着 Java 环境和组件软件技术发展得越来越成熟,本地方法将变得越
来越不重要。
利用 JNI 编程
本地方法程序设计人员应开始利用 JNI 进行编程。利用 JNI 编程隔离了一些未
知条件,例如终端用户可能正在运行的厂商的虚拟机。遵守 JNI 标准是本地库
能在给定 Java 虚拟机上运行的最好保证。例如,虽然 JDK 1.1 将继续支持 JDK
1.0 中所实现的旧式的本地方法接口,但是可以肯定的是 JDK 的未来版本将停
止支持旧式的本地方法接口。依赖于旧式接口的本地方法将不得不重新编写。
如果您正在实现 Java 虚拟机,则应该实现 JNI。我们(Javasoft 和获得许可方)
尽力确保 JNI 不会占用虚拟机实现的系统开销或施加任何限制,包括对象表示,
垃圾收集机制等。如果您遇到了我们可能忽视了的问题,请告知我们。
JDK 1.1.2 中的变化
为了更好地支持 Java 运行时环境 (JRE),在 JDK 1.1.2 中对调用 API 在几个方面
作了扩展。这些变化没有破坏任何已有代码,JNI 本地方法接口也没有改变。
JDK1_1InitArgs 结构中的 reserved0 域已被重新命名为
version。JDK1_1InitArgs 结构保存 JNI_CreateJavaVM 的初始化参数。
JNI_GetDefaultJavaVMInitArgs 和 JNI_CreateJavaVM 的调用者必须将版
本域设置为 0x00010001。JNI_GetDefaultJavaVMInitArgs 被更改为返回
jint,用于表示是否支持所请求的版本。
JDK1_1InitArgs 结构中的 reserved1 域已被重新命名为 properties。这是一
个 NULL-终结的字符串数组。每个字符串具有以下格式:
name=value
表示系统属性(该功能对应于 Java 命令行中的 -D 选项)。
在 JDK 1.1.1 中,调用 DestroyJavaVM 的线程必须是虚拟机中的唯一用
户线程。JDK 1.1.2 放松了这一限制。如果调用 DestroyJavaVM 时有多个
剩余63页未读,继续阅读
资源评论
Aqua_Hwang
- 粉丝: 0
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功