第一章:介绍

本章介绍了Java本地接口(JNI)。JNI是一个本地编程接口。它允许在Java虚拟机(VM)内部运行的Java代码与用其他编程语言(如C、C++和汇编)编写的应用程序和库进行交互。

JNI最重要的好处是它不对底层Java VM的实现施加任何限制。因此,Java VM供应商可以在不影响VM其他部分的情况下添加对JNI的支持。程序员可以编写一个本地应用程序或库的版本,并期望它能在支持JNI的所有Java VM上运行。

本章涵盖以下主题:

Java本地接口概述

虽然您可以完全使用Java编写应用程序,但在某些情况下,Java本身无法满足应用程序的需求。程序员使用JNI编写Java本地方法来处理那些无法完全使用Java编写的应用程序的情况。

以下示例说明何时需要使用Java本地方法:

通过使用JNI编程,您可以使用本地方法来:

您还可以使用JNI与调用API一起使用,以使任意本地应用程序嵌入Java VM。这使程序员可以轻松地使其现有应用程序支持Java,而无需链接VM源代码。

历史背景

来自不同供应商的VM提供不同的本地方法接口。这些不同的接口迫使程序员在给定平台上生成、维护和分发多个版本的本地方法库。

我们简要研究了一些本地方法接口,例如:

JDK 1.0本地方法接口

JDK 1.0随附了一个本地方法接口。不幸的是,这个接口不适合其他Java VM采用的主要原因有两个。

首先,本地代码将Java对象的字段作为C结构的成员进行访问。然而,《Java语言规范》没有定义对象在内存中的布局方式。如果Java VM以不同的方式在内存中布局对象,那么程序员将不得不重新编译本地方法库。

其次,JDK 1.0的本地方法接口依赖于保守的垃圾收集器。例如,对unhand宏的不受限制的使用使得需要保守地扫描本地堆栈。

Java运行时接口

Netscape提出了Java运行时接口(JRI),这是一个为Java虚拟机提供的服务的通用接口。JRI设计时考虑了可移植性---它对底层Java VM的实现细节做出了少量假设。JRI解决了各种问题,包括本地方法、调试、反射、嵌入(调用)等。

原生本地接口和Java/COM接口

微软的Java VM支持两种本地方法接口。在低级别上,它提供了一个高效的原生本地接口(RNI)。RNI提供了与JDK的本地方法接口高度的源级向后兼容性,尽管有一个主要区别。与依赖保守垃圾收集不同,本地代码必须使用RNI函数与垃圾收集器显式交互。

在较高级别上,微软的Java/COM接口为Java VM提供了一个与语言无关的标准二进制接口。Java代码可以像操作Java对象一样使用COM对象。Java类也可以作为COM类暴露给系统的其他部分。

目标

我们相信一个统一、经过深思熟虑的标准接口对每个人都有以下好处:

实现标准本地方法接口的最佳方法是让所有对Java VM感兴趣的各方参与其中。因此,我们组织了一系列关于统一本地方法接口设计的讨论。从讨论中清楚地看出,标准本地方法接口必须满足以下要求:

Java本地接口方法

我们希望采用现有方法之一作为标准接口,因为这将对必须学习不同VM中多个接口的程序员施加最小的负担。不幸的是,目前没有现有解决方案完全满足我们的目标。

Netscape的JRI是我们设想的便携式本地方法接口最接近的,也是我们设计的起点。熟悉JRI的读者会注意到API命名约定、方法和字段ID的使用、本地和全局引用的使用等方面的相似之处。然而,尽管我们尽最大努力,JNI与JRI不具有二进制兼容性,尽管VM可以同时支持JRI和JNI。

微软的RNI相对于JDK 1.0是一个改进,因为它解决了本地方法与非保守垃圾收集器一起工作的问题。然而,RNI不适合作为独立于VM的本地方法接口。与JDK一样,RNI本地方法将Java对象作为C结构访问,导致两个问题:

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

将COM作为标准Java本地方法接口的使用受到一些因素的阻碍:

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

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

编程到JNI

本地方法程序员应该编程到JNI。通过遵循JNI标准,您可以使本地库在给定Java VM中运行的机会最大化,而不受最终用户可能运行的供应商VM的未知因素的影响。

如果您正在实现Java VM,您应该实现JNI。JNI经过时间考验,确保不会对您的VM实现施加任何开销或限制,包括对象表示、垃圾收集方案等。如果您遇到我们可能忽视的任何问题,请发送反馈给我们。