收藏 分销(赏)

Java本地接口(JNI)编程指南和规范.pdf

上传人:曲**** 文档编号:13309793 上传时间:2026-02-26 格式:PDF 页数:160 大小:12.06MB 下载积分:12 金币
下载 相关 举报
Java本地接口(JNI)编程指南和规范.pdf_第1页
第1页 / 共160页
Java本地接口(JNI)编程指南和规范.pdf_第2页
第2页 / 共160页


点击查看更多>>
资源描述
Java本地接口(JNI)编程指南和规范Java本地接口(JNI)编程指南和规范(2011-01-30 13:58:32)(The Java Native Interface Programmer5 s Guide and Specification)序言这本书涉及了Java本地接口(JNI)。如果你对下列情况感兴趣,这本书将对你有用:.整合带有例如C或C+语言编写的传统代码的Java应用程序。.用例如C或C+语言编写的已存在的程序来实现Java虚拟机。.实现一个 Java 虚拟机(Java virtual machine).理解在语言互操作性上的技术说明,特别是怎样处理例如垃圾收集和多线程的特性。首先,这本书是为开发者写的。在JNI各种特性上的丰富的各种讨论,和在怎样有效 的使用JNI的有帮助的提示后,你将能发现很容易按部就班的开始使用JNI。JNI在 1997年初初始发布。这本书总结了,在Sun微系统(Sun Microsystem)上工程师和还有在 技术交流社区中大量的开发者,获得的两年经验。第二,这本书体现了各种JNI特性的设计基本原理。不仅学术界感兴趣这个,而且十 分透彻的实际理解也是高效使用JNI的先决条件。第三,这个书的一部分是为Java 2平台的JNI定义规范。JNI编程可以使用这个规范 当作参考说明书。Java虚拟机的实现必须按照规范来一致实现。关于这个规范的评论或关于JNI的问题请发送到我们的地址邮件:jnijava.sun。为了 最新的Java 2平台,或最新的Java 2 SDK release”。请访问我们的网站o为关于“Java Series的更新信息包括这本的勘误表和将要出版书的预 览,请访问java.sun/SeriesoJNI的设计引来了在Sun Microsystems和Java技术授权之间的一些列争论。JNI 是来自“Netscape的 JRI(Java Runtime Interface)的部分进化而来,JNI是“Warren Harris设计的。来自Java技术授权公司的许多人积极地参与了设计的讨论。他们包括 Russ Arun(Microsoft),Patrick Beard(Apple),Simon Nash(IBM),Ken Root(Intel),Ian El1 ision-Taylor(Microsoft),andMike Toutoghi(Microsoft)oJNI的设计也大量地得益于Sun内部设计评论,这评论来自Dave Bowen,James Gosling,Peter Kessler,Tim Lindholm,Mark Reinhold,Derek White and Frank Yellino Dave Brown,Dave Connelly,James Mcllree,Benjamin Renaud,andTom Rodrigues对JNI在Java 2 SDK 1.2上的增强做出了有意义的贡献。在俄罗斯新西伯利 亚(Novosibirsk)的兼容性测试的Carla Schroer的团队为JNI写了兼容性测试程序。在 这过程中,他们发现了原始规范不清楚或不完整的地方。JNI技术没有 Dave Bowen,Larry Abrahams,Dick Neiss,Jon Kannegaard,and Alan Baraz的管理支持将不能被开发和部署。我得到来自我的经理Dave Bowen的强有力地支持 和鼓励来写这本书。Tim Lindholm,(The Java Virtual Machine Specification 的作者,在JNI被设 计时,正主导Java虚拟机开发。Tim在虚拟机和本机接口上做了引领性的工作,提倡 JNI的使用和为这书增加了严密性和清晰度。为这本书的封面的厨房和餐厅的艺术设 计,他也提供初始的草图。这本书得益于许多同事的帮助。Anand Palaniswamy写了第十章关于一般陷阱和缺陷(on common traps and pitfalls)的部分。Janet Keonig细心地预读初始的草稿和贡献了许多 哦有用的意见。Beth Stearns根据在线的JNI指南写了第二章的草稿。我从 Craig J.Bordelon,Michael Brundage,Mary Dageforde,Joshua Engel and Elliott Hughes处得到关于这本书草稿有价值的评论。Lisa Friendly,The Java Series的编者,有助于这本书的编写和出版。Ken Arnold,The Java Programming Language得到作者,首先提出了 JNI书的编写。我要感谢在整个 过程中Mike hedrikson和Marina Lang给的帮助和耐心在Addison-Wesley出版社。Diance监督了生产流程从复制,编辑和最后的打印。在过去的几年里,我和一群在Sun Micorsystems上的Java软件中有才能和奉献的人一 起,有特权的工作,特别是original,HotSpot and Sun Labs虚拟机团队成员。这本书 献给他们。Java本地接口(JNI)编程指南和规范(第一章)(2011-01-30 14:06:36)第一部分,介绍和指南(Part One:Introduction and Tutorial)第一章介绍JNI是Java平台的一个强大的功能。使用JNI的应用程序能能混合用例如C和 C+语言编写的本地代码(native code),和用Java编程语言编写的代码。JNI允许编 程人员,在不丢弃在传统编码上的投入,来利用Java平台功能。因为JNI是Java平台 的一部分,编程人员立马解决互操作的问题,同时解决和Java平台的所有的实现一起工作 的问题。这本书是JNI的编程指导和参考说明。书包含三个部分:.第二章通过简单的例子,介绍JNI。这个说明,是给不熟悉JNI的初始使用者的。.第三章到第十章构建了编程者的指南,这给出了大量JNI功能的全面介绍。我们通过 一系列短而详细描述的例子来展示JNI不同的功能,和展示被证明在JNI编程中有用的 技术。.第十一章到第十三章为所有的JNI类型和函数,展示明确的规范。这些章也被组 织为参考说明服务。这本书尝试吸引广泛的用户,他们对JNI不同需求的。这指南和编程引导是为初始编程 者,但有经验的开发者和JNI的实现者可以找到更有用的参考章节在这指南和编程引导 中。大多数读者将可能是开发者,他们用JNI来写应用程序。这本书的你术语将暗指 用JNI”编程的开发者(program with the JNI)o 相反是JNI实现者(JNI implementors)或使用 JNI写的应用程序的终端用户。这本书假设你有Java,C和C+编程语言的基本知识。如果没有,你可以参考许多有 用的优秀的书本:Ken Arnold and James Gosling(Addison-Wesley,1998)写的 The Java Programming Language,Second Edittion”,Brian Kernighan and Dennis Ritchie(Prentice Hall,1988)写的TheC Programming Language,Second Edition和 Bjarne Stroustrup(Addison-Wesley 1997)写的The C+Programming Language,Third Edition”.这章剩余的部分介绍JNI的背景,作用和演化。1.1 The Java Platform and Host Environment(Java 平台和主机环境)这本书时间用Java编程语言和用本地编程语言(C,C+等(etc.)来写应用程序.让我们 先为这些语言,明确正确的编程环境区域。Java平台的编程环境包含Java虚拟机(VM)和Java应用程序编程的接口(Java Application Programming Interface(API)。Java”应用程序是用Java编程语言编写 的,被编译成一个独立于机器(machine-independent)二进制类格式.一个类在任何Java 虚拟机上执行实现。Java的API包含预定义的类集合。Java平台的任何实现被假设支持 Java编程语言,虚拟机和API。主机环境(host environment)术语代表主机操作系统,本地库组,和CPU指令集。用本 地变成语言(native programming languages)如C和C+编写本地应用程序(Native application),被编译特定主机的二进制编码,和被连接到本地库。本地应用程序和本地 库是典型依赖于特定主机环境。为一个操作系统建立的一个C应用程序,例如,典型不 能呢工作在另一操作系统上。“Java平台被一般的配置在主机环境的上面。例如,JRE(Java Runtime Enviroment)是Sun产品,它支持Java平台运行在例如Solaris和Windows的存在操作系统上。Java平台提供一组特性,应用程序能依赖独立于底下的主机环境。1.2 Role of the JNI(JNI 的作用)当Java平台被配置在主机环境的顶层上,平台对于允许Java应用程序,带有用其他 语言编写地本机编码工作,是需要或必须的。编程者已经开始采用Java平台来建立用C 和C+编写的传统的应用程序。因为在遗留代码上存在投资价值,然而,Java应用程 序将和 C 和 C+代码共存许多年。JNI的一个强大的特性是允许你来利用Java平台,但利用的代码仍然用其他语言来编 写。作为Java”虚拟机(Jave virtual machine)执行的一部分,JNI是一个双向接口,允许Java应用程序调用本地代码,反之亦然(vice versa)o Figure 1.1(图1.1)说明 JNI 的作用。Java application Java virtual machine(JNI)Native applicationand library implementation and library|-Host enviroment-1Figure 1.1 Role of JNIJNI被设计为处理你需要联合Java应用程序和本地代码的情况。做为一个双向接 口,JNI”能支持两种本地编码:本地库(native libraries)和本地应用程序(native application)。.你能使用JNI来编写,允许Java应用程序来调用在本地库中实现的函数的本地方法(native method)。Java应用程序,通过和他们调用在Java编程语言中实现的方法一样 办法,调用本地方法。然而幕后,本地方法是用另一种语言实现的和位于本地库中。.JNI”支持一个调用接口(invocation interface),这个接口允许你嵌入一个Java虚拟 机执行到你本地应用程序中。本地应用程序能和执行Java虚拟机的本地库链接,同样因 此用调用接口来执行用Java编程语言编写的软件控件。例如,一个用C写的web浏览 器能在嵌入式Java虚拟机执行中执行下载applets:1.3 Implications of Using the JNI(使用 JNI 的影响)记住一旦一个应用程序使用了 JNL它冒险失去了 Java平台的两个好处。首先,依赖JNI的Java应用程序不再可以在多种主机环境中运行。即使用Java编程 语言编写的应程序的部分可移植到多种主机环境,它将需要重新编译用本地编程语言编写 的应用程序的部分。其次,Java编程语言的类型安全和可靠,然而本地语言例如C或C+是没有的。因 此,当你用JNI来写应用程序时你必须额外地细心。一个有恶意的本地方法可能破坏整个 应用程序。因为这个原因,Java应用程序在调用JNI特性前,接受了安全检查。作为一般规则,你应该构建应用程序时,在尽量少的类中定义本地方法。这就意味着在 本地代码和应用程序剩余代码之间有一个明显的隔离。1.4 When to Use the JNI(什么时间使用 JNI)在你从事一个使用JNI的工程前,后退一步调查一下是不是有根合理的替代方案是值 得的。像上一章提到的,当和严格用Java编程语言写的应用程序比时,使用JNI的应 用程序有固有的缺点。例如,你失去Java编程语言的类型安全保证。大量的可选方案也允许Java应用程序和其他语言编写的代码互操作的。例如:.Java应用程序通过一个TCP/IP链接和其他进程间通信机制(other inter-process communication(IPC)mechanisms)来和本地应用程序交流。.一个Java应用程序可以通过JDBC API连接到原来的数据库上。.一个Java应用程序可以利用分布式对象技术例如Java IDL API这些替代方案的一般特征是Java应用程序和本地代码放在不同的进程中(在一些案例 中在不同的机器上).进程隔离提供了一个重要的好处。进程提供了地址空间的保护能够最 大限度的错误隔离,一个奔溃的本地应用程序不会立马终止通过TCP/IP和它通讯的 Java 应用程序。然而有时,你可以发现对于Java应用程序必须和驻留在一样进程中(resides in the same process)的本地代码交流。这是JNI”很有用的时候。思考,例如,下面的情况:Java API可能不支持应用需要的某个依赖主机的特性。例如:一个应用程序可能需要 执行特别的文件操作,但Java API不支持。然而通过另一个进程来操作文件是繁琐和低 效的。.你可能需要访问一个存在的本地库,不愿意花费在不同进程间的数据的拷贝和复 制的开销。在同一个进程中载入本地库是更有效率的。.横跨多个进程的应用程序可能导致不可接受的内存占用。如果这些进程需要驻留在同 一个客户端机器上,这是真确的。载入一个本地库到存在本机进程中,应用程序需要比启 动一个新的进程并载入这个库到新进程中需要的更少的系统资源。.你可能需要在一个低级语言中执行一小段时间要求严格的代码(实时反应的代码)(time-critical code),例如汇编。如果一个3D增强应用程序消耗大量的时间在图形 绘制中,你可以发现必须用汇编代码写图形库的核心部分来达到最好性能。总之,如果你的Java应用程序必须和驻留在一个进程中的本地代码互操作,就得用1.5 Evolution of the JNI(JNI 的演化)从Java平台的很早的时候,对于Java应用程序对和本地代码互操作的需要的就被认 识。Java平台的第一版本,JDK(Java Development Kit)release 1.0”,就包含1个 本地方法接口。它允许Java皮用程序调用其他语言如C和C+编写的函数。许多第三 方的应用程序和Java类库的实现(例如,包扩java,lang,java,io and java),都依赖本地 方法接口来访问在底层主机环境中的特性。不幸的是,在JDK release 1.0中的本地方法接口发现两个主要的问题:.首先,本地代码,用C结构体的成员作为对象,来访问域。然而,Java虚拟机规范没 有定义对象在内存中怎样布置。如果一个Java虚拟机的实现以一种方法布局这些对象,不同于本地方法接口的设定方法,你必须重编译本地方法库。.其次,在JDK release 1.0中本地方法的接口依赖于一个保守的垃圾收集器,因为本 地方法在虚拟机中得到对象的直接指针。任何使用更先进的垃圾收集算法的虚拟机的实 现,不可能支持在JDK release 1.0中的本地方法接口。设计JNI来克服这些问题。一个接口能被在不同主机环境中的所有的Java虚拟机的实 现支持。有JNI:.每个虚拟机的实现者能支持很大体积的本地代码。.开发工具商不必处理不同种类的本地接口。.最重要的,应用程序编程者可以写一个版本的本地代码,这个版本将能在不同的Java 虚拟机实现上运行。JNI首先在JDK release 1.1中被支持。然而,JDK release 1.1内在仍然使用老 风格的本地方法(和在JDK release 1.0中一样)来执行Java APIs.在“Java 2 SDK release 1.2中不再是这样(以前被称为JDK release 1.2).本地方法被重写,为了确定 JNI 标准。JNI是被所有Java虚拟机实现支持的本机接口。从JDK release 1.1开始,你应该 用JNI编程。老风格本地方法接口仍然在Java 2 SDK release 1.2中被支持,但将在 未来高级的Java虚拟机实现中不被支持。Java 2 SDK relase 1.2包含了大量的JNI增强性能。这个增强是向后兼容的。JNI 的将来的演化将兼容保留所有的二进制。1.6 Example Programs(例子程序)这本书包含大量例子程序,它们来证明JNI特性。典型的例子吃呢供需包含多段用Java编程语言和C或C+本地编程语言编写的代码片段。有时本地编码参考了在 Solaris和Win32系统中的本机特定特性。我们也显示了怎样使用JDK和Java 2SDK release带有的命令行工具(例如 javah)来建立JNI程序。记住JNI的使用被限制在指定的主机环境或指定的应用开发工具中。这本书关心的是 写代码,不是在使用工具编译和运行编码上。和JDK和Java 2 SDK release捆绑的命 令行工具是很原始的。第三方的工具可以提供改善的方法编译使用JNI的应用程序。我们 鼓励你参考和你选择的开发工具绑定的 JNI相关的文档。你能下载这本书中例子的源代码,和这本书的最新更新,来自下面web地址:Java本地接口(JNI)编程指南和规范(第二章)(2011-01-30 14:18:38)第二章开始这章通过一个使用Java Native Interface(JNI)的一个简单例子来引导你。我们将携 一个Java应用程序,它调用一个C函数来打印Hello World!2.1概要Figure 2.1(图2.1)说明这个进程为使用J明或Java 2 SDK releases来写的一个 简单的Java应用程序,它调用一个C函数打印Hello World!这个过程包含以下几步:1.创建一个类(HelloWorld.java)宣布一个本地方法。2.用javac来编译HelloWorld源代码文件,产生class文件“HeHoWorld.class.javac编译器是JDK或Java 2 SDK releases提供的。3.使用 javah-jni来产生一个C头文件(HelloWorld.h),它包含函数的原型为本地 方法的实现。javah工具是JDK或Java 2 SDK releases提供的。4.写C的本地方法的实现(HelloWorld.c)。5.编译C的实现为一个本地库,创建HelloWorld.dll或libHelloWorld.so文件。使用在本机环境中可用的 C 编译器和链接器。6.使用“java runtime interpreter77(java 实时解释器)来运行HeHoWorlcT程序。“class”文件(HelloWorld.class)和本地库(HelloWorld.dll or libHelloWorld.so)被实 时的载入。这章剩余的部分解释这些步骤的细节。1.Create a classthat declares thenative method|-HelloWorld.java2.3.Use javac Use javah toto compile the|-generate headerprogram|fileI I I|-HelioWorld,class-1|-HelloWorld.hI I|4.|-Write the C|implementation|-of the native method|HelloWorld.c Compile C|Code and generate|-native libraryI 6.1|-Run the program|一 HelloWorld.dllusing the java|interpreter Hello World!Figure 2.1 Steps in Writing and Running the Hello World Program2.2 申明本地方法(Declare the Native Method)你通过用Java编程语言写下面的程序开始。这个程序定义一个类,名字为“HelloWorld”,包含一1 个本地方法print。class HelloWorld(private native void print();public static void main(String args)new HelloWorldO.print();staticSystem.loadLibrary(/zHelloWorld/z);“HeHoWorlcT类定义开始申明了print本地方法。“main方法实例化“HenoWorld”类,同时调用了print本地方法为这个实例。这个类定义的最后部分是一个静态初始 化,来载入包含print本地方法实现的本地库。在本地方法如print的声明和用Java编程语言声明的规则的方法之间有两个不同。本 地方法的声明必须包含native修饰字符。这个native修饰字符指明这个方法用另一种 语言来实现。本地方法声明是用分号终止的,声明终止符号,因为在这类自身中本地方法 没有实现。我们将在单独的C文件中实现print方法。在本地方法print被调用前,实现print的本地库必须被载入。这个例子中,我们在 HeHoWorld类的静态初始化中载入本地库。Java虚拟机自动地运行静态初始化,在“HeHoWorld类中调用任何方法前,因此保证在print本地方法被调用前,本地库被载 入。我们定义了一个main方法能运行HelloWorlcT类。HelloWorld.main用和它调用一 般规定方法一样方法调用本地方法 print:“System.loadLibrary需要一个库名字,定位和这个名字相应的本地库,载入这个本地 库到应用程序。我们将在这本书后面讨论详细地载入过程。现在简单地记住为了“System.loadLibrary(HelloWorld)成功,我们必须创建在Win32”上名叫HelioWorld,dll,或在Solaris上名叫libHelloWorld.so的本地库。2.3 编译HelloWorld类你已经定义了HelloWorld类后,保存源代码在HelloWorld.java文件中。然后用 JDK或Java 2 SDK release自带的javac编译器编译源代码文件:javac HelloWorld.java这个命令将在当前的目录中产生一个HelloWorld.class文件。2.4创建本地方法的头文件下一步我们将使用javah工具来产生一个JNI格式头文件,当用C语言来实现本地 方法时这头文件是有用的。你能在HelloWorld类上运行javah,如下:javah-jni HelloWorld头文件名字是一个带有.h的类名,.h扩展它的结尾。上面 显示的命令产生了一个名为HelloWorld.h的文件。我们这儿将不再完整地列出产生的头 文件。头文件最重要的部分是Java_HenWorld_print的函数原型,它是C函数实现了“HelloWorld.print方法:JNIEXPORT void JNICALLJavaHelloWorldprint(JNIEnv*,jobject);因为现在,忽略JNIEXPORT和JNICALL宏。我们可能已经注意到,即使虽然对应地本 地方法的声明不接受参数,但是本地方法C的实现接受两个参数。对于每个本地方法的实 现的第一个参数都是一个 JNIEnv 接口的指针第二个参数是 HelloWorld 对象自身的一个 参考(在C+中就像this指针)。我们将在这本书的后面讨论怎样使用JNIEnv接口指 针和 jobject 参数,但这个简单的例子忽略这两个参数。2.5写本地方法的实现通过javah产生的JNI风格头文件帮助你为本地方法来写C或C+的实现。你写的 函数必须按照在产生头文件中的详细定义的原型来。你能实现HelloWorld.print方法在“HelloWorld.c的“C文件中。如下(as follows):#include#include#include HelloWorld.hJNIEXPORT void JNICALLJavaHelloWorldprint(JNIEnv*env,jobject obj)printf(Z/Hello World!nz/)return这个本地方法的实现是简单的。它使用printf函数来显示一个字符串HelloWorld!然后放回。对于前面提到的俩那个参数,JNIEnv指针和对象(object)的参考 被忽略。这个 C 程序包含三个头文件:.jni.h 这个头文件提供了本地编码需要调用的JNI接口的信息。当写本地方法 时,你必须总是包含这个头文件在你的 C 或 C+源代码中。.stdio.h 上面的代码片段总是包含stdio.h,因为它使用了printf函数。.HelloWorld.h-你用“javah产生的头文件。它为 Java HelloWorld print 函数包含了 C/C+原型。2.6编译C源代码和创建一本地库记住当你在HelloWorld.java文件中创建“HelloWorld”类的时候,你包含了一行代码,它载入一个本地库到程序中:System.loadLibrary(/zHelloWorld/z);现在所有需要的C源代码都写了,你需要编译HelloWorld.c和建立本地库。不同的操作系统支持不同的方法来建立本地库。在Solaris,下面的1命令构建一个叫 libHelloWorld.so的共享库:cc-G-1/java/include-1/java/include/Solaris HelloWorld.c-o libHelloWorld.so-G 可选命令 C 编译器来产生一个共享库来替代一个规定的 Solaris 的可执行文件。因为本书的篇幅的限制,我们把命令行打断成两行。你需要输入命令在单独一行,或放置 这命令在一个脚本文件中。在Win32中,下面命令,来使用Microsoft Visual C+编译 器,构建一个动态链接库(DLL)(dynamic link library)“HelloWorld.dll”:cl-Ic:javainclude-Ic:javaincludewin32-MD-LD HelloWorld.c-FeHelloWorld.dll-MD可选项保证HelloWorld.dH被用Win32多线程C库来链接。-LD选项命令 C编译器来产生一个DLL来替代一个规定的Win32可执行的文件。当然,在Solaris 和Win32”上,你需要输入包含的目录,它对应在你自己机器上安装目录。2.7运行程序在这时,你为运行程序准备了两个控件。class文件(HelloWorld.class)调用本地方 法,和本地库(HelloWorld.dll)实现本地方法。因为HelloWorld类包含它自己的main方法,你可以在Solaris或Win32上运行,如下(asfollows):java HelloWorld你应该看到如下输出:Hello World!重要的是为你程序运行时正确地设置本地库路径。这个本地库路径是在Java虚拟机搜 索的列表目录中,当载入本地库时。如果你没有真确的建立本地库路径,你将看到和下面 相识的一个错误:java.lang.UnsatisfiedLinkError:no HelloWorld in library pathat java.lang.Runtime.loadLibrary(Runtime,java)at java.lang.System.loadLibrary(System,java)at HelloWorld.main(HelloWorld.java)确保本地库驻留在本地库路径中的一个目录中。如果你在Solaris系统上运行,LD_LIBRARY_PATH环境变量被用来定义本地库的路径。确保它包含了包含 z/libHelloWorld.so”文件的目录名字。如果libHelloWorld.so”文件是在当前目录中。你 可以发布如下两个命令在标准的shell(sh)或KornShell(ksh)来建立LD_LIBRARY_PATH 恰当的环境变量:LD_LIBRARY_PATH=.export LD_LIBRARY_PATH在C shell(csh or tcsh)中同样的命令是像下面:setenv LD_LIBRARY_PATH.如果你运行在Window 95或Windows N机器,你确保HelloWorld.dll是在当期目 录下,或在你PATH环境变量的列表的目录中。在Java 2 JDK 1.2 release中,你也能在 java命令行上详细说明本地库路径作为一 个系统属性如下:java-Djava.library.path=.HelloWorld-D命令行选项设置一个 Java 平台系统属 性。设置java,library,path”属性为.“命令 Java virtual machine(Java 虚拟机)来在 当前目录中搜索本地库。Java本地接口(JNI)编程指南和规范(第三章)(2011-01-30 14:26:43)第二部分:编程者的指南(Part Two:Programmer5 s Guide)第三章基本类型,字符串和数组(Basic Types,Strings,and Arrays)当面对带有本地代码的Java的应用程序时,程序员问的最通常的问之一,是在Java编 程语言中的数据类型怎样对映到本地编程语言例如C和C+中的数据类型。在上一章节 中出现的Hello World!例子中,我们没有传递任何参数到本地方法中,本地方法没有放 何任何结果。本地方法简单地答应了一个消息和放回。实际上,大多数程序将需要传递参数给本地方法,和也从本地方法接受结果。在这章节 中,我们将描述怎样转换数据类型在用Java编程语言写的代码和实现本地方法的本地代 码中。我们将从基本的类型开始,如整型(integers)和普通的对象类型,如字符串(stirngs)和数组(arrays).我们推迟任意对象的彻底解决到下一章,在下一章我们将解释 本地代码能怎样访问域和调用方法。3.1 一个简单本地方法(A Simple Native Method)让我们从一个简单的例子开始,这个例子不同于在上一章的HelloWorld程序。这个例 子程序,Prompt.java,是一个打印字符串,等待用户输入,然后返回一行用户的输入的 本地方法。这个程序的源代码如下(as follows):class Prompt(/native method that prints a prompt and read a lineprivate native String getLine(String prompt);publie static void main(String args)Prompt p=new Prompt();String input=p.getLine(Type a line:);System,out.printin(/zUser typed:/z+input);static System.loadLibrary(Prompt);“Prompt.main”调用本地方法Prompt.getLine来得到用户的输入。静态初始化调用了“System.loadLibrary方法来在载入一个本地库“Prompt”。3.1.1 为实现本地方法的 C 原型的 Prototype for Implementing the Native Method)“Prompt.getLine方法能用下面的C函数来实现:JNIEXPORT jstring JNICALLJavaPromptgetLine(JNIEnv*env,jobject this,jstring prompt);你能用 javah 工具来产生一个包含上面函数原型的同文件。JNIEXPORT 和 JNICALL 宏(被定义在 jni.h头文件里)确保这个函数从本地库中导出和C编译器产生带有为这个 函数正确调用约定的代码。C函数的名字被格式为连接Java_前缀,类名和方法名。11.3 部分包含了一个更精确的怎样格式化C函数名字的描述。3.1.2 本地方法参数(Native Method Arguments)在2.4部分中被简单的讨论,本地方法实现如Java_Prompt_getLine接受两个标准参 数,除了参数在本地方法中被声明外。第一参数,JNIEnv接口指针,指向一个包含指向 函数表的地方。在函数表中每个条目都指向一个JNI函数.本地方法总是通过这些JNI 函数的一个来访问在Java虚拟器中的数据结构。Figure 3.1说明JNIEnv接口指针。JNIEnv*|-pointer-Pointer-an interface function(Internal virtual Pointer-an interface functionmachine data Pointer-an interface functionstructures)Figure 3.1 the JNIEnv Interface Pointer对于本地方法是一个静态或是一个实例方法,第二个参数不同。对一个实例化的本地方 法的第二个参数,是一个关于被调用方法的对象的参考,类似于在C+中的this指 针。对于一个静态的本地方法的第二个参数,是一个定义这个方法的类的参考。我们的例 子,Java_Prompt_getLine,实现了一个实例化的本地方法。因此这个jobject参数是 对象(object)自己的参考。3.1.3 类型的映射(Mapping of Types)在本地方法声明中参数类型有对应的在本地编程语言中的类型。JNI定义了一套 C 和,(+类型来对应在白血编程语言中的类型。在Java编程语言中的两种类型:基本来型如int,float,和char;和参考类型如“classes,instances和arrays”.在Java编程语言中,strings 是 java.lang.String类的一个实例。JNI不同地对待基本类型和参考类型。基本类型的映射是简单易懂的。例如,在Java编程语言中的int类型映射到C/C+的jint类型(定义在jni.h作为一个有符 号32bit整型),同时在Java编程语言中的float类映射到C+的jfloat类型(定义 在jni.h作为一个有符号32bit浮点数),12.1.1部分包含了在JNI中定义的所有基本类 型的定义。JNI传递objects到本地方法作为不透明的引用(opaque references)o不透明的引 用是一个C指针类型,引用了在Java虚拟机中的内部数据结构。然而,内部数据结构的 精确安排,对编程者是隐藏的。本地代码必须通过恰当的JNI函数处理下面的对象(objects),JNI函数通过JNIEnv接口指针是可用的。例如,为java.lang.String对 应的JNI类型是jstring。一个jstring引用(reference)的确切值是和本地代码无关 的。本地代码调用JNI函数例如GetStringUTFChars来访问一个string的内容。所有的JNI引用都是类型jobject。为了方便和增强类型的安全,JNI定义了一组引 用类,它们概念
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 品牌综合 > 行业标准/行业规范

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服