JNI介绍

第一章 介绍

这一章介绍的是Java本地接口(JNI).JNI是本地编程的接口,它允许运行在java虚拟机里面的java代码调用使用其它语言编写的库和应用,例如C,C++等其它语言.

JNI最有利的地方在于它不对底层java虚拟机的实现添加任何限制。因此,Java虚拟机供应商可以添加对JNI的支持而不影响虚拟机的其它模块.程序员只需要编写一个版本的本地应用或者库便能够在所有版本的java虚拟机中运行.
这一章节涵盖了下面这几个话题:

java本地接口概述
历史背景
面向对象的
Java本地接口方法
面向JNI编程
改变

java本地接口概述

如果你在早期就已经使用过java编写应用,有些情况下单独使用java编写并不能满足应用需求。程序员使用JNI编写Java 本地方法来解决应用不能完全使用java来实现的状况。

下面这几个例子说明了你需要使用java本地方法:

1.拥有的标准java类库不支持应用所需的与平台相关的特性.
2.你已经使用其他语言编写好了库,并希望能够通过java来调用它.
3.你想要使用低级的语言(例如汇编)实现一小部分高效的代码。

通过编写jni程序,你可以使用本地方法进行如下操作:

1.创建,检查以及更新java对象(包括数组和字符串)
2.调用java方法
3.捕获以及抛出异常
4.加载类和类所包含的信息
5.进行运行时类型检查

你还可以将JNI与调用API配合使用,以允许任意本机应用程序嵌入Java 虚拟机中.程序员将很轻松地让自己现有的应用程序支持Java并且无需与虚拟机源码牵扯.

扫描二维码关注公众号,回复: 2512712 查看本文章

历史背景

不同的虚拟机供应商提供不同的本地方法接口.这些不同的接口强制让程序员在已有的平台上去生产维护以及发布多种版本的本地方法库.
我们简要地研究一些本地方法接口,例如:

JDK1.0 本地方法接口
网景 的java运行时接口
微软 的原生本地接口和java/COM接口.

JDK1.0 本地方法接口

发布的JDK1.0本身就携带有本地方法接口.不幸的是,有两个主要的原因让接口很难被其他 的Java虚拟机所采用.

首先,本地代码以C语言结构成员去访问java对象的字段,然而,java语言并没有定义对象在内存中是如何分布的.如果java虚拟机将对象分布在不同的内存,开发者不得不重新编译本地方法库.

第二,JDK 1.0中的本地方法接口依赖于一个保守的垃圾回收器.无限制地使用宏,例如,垃圾回收器有必要保守地去检测本地栈.

Java运行时接口

网景提出了java运行时接口(JRI),java虚拟机提供的服务通用接口.JRI设计考虑到了移植性,对底层Java虚拟机的实现细节几乎没有假设.JRI处理了广泛的问题,其中包括了本地方法,调试,反射,嵌入(调用)等.

原生的本地接口和java/COM接口

微软的java虚拟机支持两类本地方法接口,在低层次时,它提供了一种有效的原生本地接口为JDK本地方法接口提供了高度的源级向后兼容性.尽管有一点不同,不依赖于保守的垃圾回收,本地代码必须使用RNI函数与垃圾收集器进行确切地交互.

在更高的层次上,微软的JAVA/COM 接口提供了一种语言依赖标准二进制接口给java虚拟机.java代码使用COM对象就如同使用使用java对象.Java类也可以作为COM类暴露给系统的其余部分.

目标

我们相信,一个统一的、精心设计的标准接口可以为每个人提供以下好处:

每个供应商都能支持更庞大的本地代码.
构件工具将不必再去维护不同类型的本地方法接口.
应用开发人员也将不必再去编写不同版本的本地代码来让其运行在不同的虚拟机上.

java本地接口方法

我们希望采用已有的方法作为标准标准的接口,因为这将给开发人员带来不同虚拟机的多个接口的学习负担。不幸的是,并不存在方案能够完美解决这个问题。

网景的JRI是最接近我们设想的一个可移植的本地方法接口,并且作为我们设计的起点。 熟悉JRI的读者将注意到API命名约定中的相似之处,方法和字段ID的使用,本地和全局引用的使用等等。 尽管我们尽最大的努力,但是JNI不是与JRI二进制兼容的,尽管虚拟机可以支持JRI和JNI。

微软的RNI是对JDK 1.0的一个改进,因为它解决了使用非保守的垃圾回收器的本机方法的问题。 然而,RNI不适合作为VM独立的本地方法接口。 像JDK,RNI本地方法访问Java对象作为C结构,会导致两类问题:

RNI对本地代码暴露了内部Java对象的布局。
直接访问 作为C结构的Java对象使得不可能有效地并入在高级垃圾回收算法中必需的“写屏障”。

作为二进制标准,COM确保不同VM之间的完全二进制兼容性。 调用COM方法只需要一个间接调用,这只需要很少的开销。 此外,COM对象在解决版本化问题上是对动态链接库的一个很大的改进。

然而,使用COM作为标准Java本地方法接口受到以下几个因素的阻碍:

首先,所需的Java / COM接口缺乏某些函数,如访问私有字段和抛出一般异常。

第二,Java / COM接口自动提供的标准IUnknown和COM IDispatch接口Java对象,所以本机代码可以访问公共方法和字段。不幸的是,IDispatch接口并不处理重载Java方法和匹配方法名称不区分大小写。此外,所有的Java方法通过IDispatch接口包装执行动态类型检查和约束进行暴露。这是因为IDispatch接口设计使用了弱类型语言的设计思想(如Basic)。

第三,取代处理个人底层函数,COM允许软件组件(包括成熟的应用程序)一起工作。我们认为对待所有Java类或底层的本地方法作为软件组件是不恰当的。

第四,直接采用COM是受到缺乏在UNIX平台上支持的阻碍。

尽管Java对象作为COM对象并不暴露给本机代码,JNI接口本身与COM是二进制兼容的。JNI使用相同的跳表结构和调用约定COM。这意味着,一旦跨平台支持COM可用,JNI可以成为一个COM接口的Java VM。

JNI不被认为是给定Java 虚拟机支持的唯一本地方法接口。 标准接口使程序员受益,他们希望将其本地代码库加载到不同的Java 虚拟机中。 在一些情况下,程序员可能必须使用底层的虚拟机特定接口来实现最高效率。 在其他情况下,程序员可能使用更高层的接口来构建软件组件。 事实上,随着Java环境和组件软件技术变得越来越成熟,本地方法将逐渐失去意义。

面向 JNI 编程

本地方法的程序员应该面向 JNI 编程,面向 JNI 编程可以隔离未知数,例如终端用户可能正在运行供应商的虚拟机。通过符合JNI标准,您将为本地库提供在给定Java 虚拟机中运行的最佳机会。

如果要实现Java 虚拟机,应该实现JNI。 JNI已经过时间测试,并确保不对虚拟机实现施加任何开销或限制,包括对象表示,垃圾回收方案等。 如果您遇到任何我们可能忽略的问题,请给我们您的反馈。

改变

从Java SE 6.0开始,已弃用的结构JDK1_1InitArgs和JDK1_1AttachArgs已被删除,取而代之的是使用JavaVMInitArgs和JavaVMAttachArgs。

猜你喜欢

转载自blog.csdn.net/u013560890/article/details/53373957
JNI