﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-漫步红林-文章分类-JNI</title><link>http://www.blogjava.net/hyint/category/37810.html</link><description>品味技术与生活之间的差距，追求代码与国画之间的艺术.</description><language>zh-cn</language><lastBuildDate>Sun, 29 Mar 2009 20:15:09 GMT</lastBuildDate><pubDate>Sun, 29 Mar 2009 20:15:09 GMT</pubDate><ttl>60</ttl><item><title>JNI  ------ 入门 &lt;二&gt;</title><link>http://www.blogjava.net/hyint/articles/258623.html</link><dc:creator>苦瓜</dc:creator><author>苦瓜</author><pubDate>Mon, 09 Mar 2009 08:59:00 GMT</pubDate><guid>http://www.blogjava.net/hyint/articles/258623.html</guid><wfw:comment>http://www.blogjava.net/hyint/comments/258623.html</wfw:comment><comments>http://www.blogjava.net/hyint/articles/258623.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hyint/comments/commentRss/258623.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hyint/services/trackbacks/258623.html</trackback:ping><description><![CDATA[从Java 1.1开始，Java Native Interface <br />
&nbsp;&nbsp;&nbsp; (JNI)标准成为java平台的一部分，它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言，尤其是C和C++而设计的，<br />
但是它并不妨碍你使用其他语言，只要调用约定受支持就可以了。让我们看一些使用JNI的简单例子吧。<br />
<br />
使用java与本地已编译的代码交互，通常会丧失平台可移植性。但是，有些情况下这样做是可以接受的，甚至是必须的，比如，使用一些旧的库，<br />
与硬件、操作系统进行交互，或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。 <br />
<br />
开始：<br />
如果你习惯了使用JNI，你就不会觉得它难了。既然本地方法是由其他语言实现的，它们在Java中没有函数体。但是，所有本地代码必须用本地关<br />
键词声明，成为Java类的成员。清单A演示了一个简单的类，它申明了一个本地的（native），静态的（static）方法：sum。<br />
<br />
写完了你的Java类，接下来就要写本地代码。本地方法符号提供一个满足约定的头文件，使用Java工具可以很容易地创建它而不用手动去创建。<br />
你对Java的class文件使用javah命令，就会为你生成一个对应的C/C++头文件。清单B就是为清单A的Test1类创建的头文件。注意：它创建了一个<br />
C/C++函数：Java_Test1_sum。 <br />
<br />
执行本地方法：<br />
<br />
一旦你有了这个头文件，你就需要写头文件对应的本地方法，就像我在清单C做的那样。<br />
<br />
注意：所有的本地方法的第一个参数都是指向JNIEnv结构的。这个结构是用来调用JNI函数的，（我会在另一个章节中讨论）。第二个参数jclass的意义，<br />
要看方法是不是静态的（static）或者实例（Instance）的。前者，jclass代表一个类对象的引用，而后者是被调用的方法所属对象的引用。最后的两个<br />
jint参数表示了Java方法的 int参数。<br />
<br />
返回值和参数类型根据等价约定映射到本地C/C++类型，如表A所示。有些类型，如清单B里面的两个jint参数，在本地代码中可直接使用，而其他类型<br />
只有通过JNI调用操作。<br />
<br />
表A 　　<br />
&nbsp;&nbsp;&nbsp; Java类型&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本地类型&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 描述<br />
&nbsp;+---------------+--------------------+--------------------------+&nbsp;&nbsp;&nbsp; 　　<br />
&nbsp;|<u>&nbsp; boolean&nbsp;&nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jboolean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; C/C++8位整型 　　&nbsp;&nbsp; &nbsp; </u>|<br />
&nbsp;|<u>&nbsp; byte&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jbyte&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; C/C++带符号的8位整型&nbsp; </u>|<br />
&nbsp;|<u>&nbsp; char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jchar&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; C/C++无符号的16位整型 </u>|　<br />
&nbsp;|<u>&nbsp; short&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jshort&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; C/C++带符号的16位整型 </u>|　<br />
&nbsp;|<u>&nbsp; int&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; jint&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; C/C++带符号的32位整型 </u>|　<br />
&nbsp;|<u>&nbsp; long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jlong&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; C/C++带符号的64位整型 </u>|　<br />
&nbsp;|<u>&nbsp; float&nbsp; &nbsp; &nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; jfloat&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; C/C++32位浮点型 　　&nbsp; </u>|<br />
&nbsp;|<u>&nbsp; double&nbsp; &nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jdouble&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; C/C++64位浮点型 　 &nbsp;&nbsp; </u>|<br />
&nbsp;|&nbsp; Object&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jobject 有对应&nbsp; |&nbsp;&nbsp;&nbsp; 任何Java对象，或者没&nbsp; |<br />
&nbsp;|<u>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; | &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; 有</u><u>java 类型的对象</u><u> &nbsp; &nbsp; </u>|&nbsp; <br />
&nbsp;|<u>　Class&nbsp; &nbsp; &nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; jclass&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; Class对象 　　&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; </u>|<br />
&nbsp;|&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jstring&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 字符串对象 　　&nbsp; &nbsp; &nbsp;&nbsp; |<br />
&nbsp;+---------------+--------------------+--------------------------+<br />
&nbsp;| Object[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jobjectArray &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 任何对象的数组 　&nbsp;&nbsp; &nbsp; |<br />
&nbsp;| boolean[]&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jbooleanArray&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 布尔型数组 　　&nbsp; &nbsp; &nbsp;&nbsp; |<br />
&nbsp;| byte[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jbyteArray&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 比特型数组 　　&nbsp; &nbsp; &nbsp;&nbsp; |<br />
&nbsp;| char[]&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jcharArray&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 字符型数组 　　&nbsp; &nbsp; &nbsp;&nbsp; |<br />
&nbsp;| short[]&nbsp;&nbsp; &nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; jshortArray&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 短整型数组 　　&nbsp; &nbsp; &nbsp;&nbsp; |<br />
&nbsp;| int[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jintArray&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 整型数组 　　&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; |<br />
&nbsp;| long[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jlongArray&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 长整型数组&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
&nbsp;| float[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jfloatArray&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 浮点型数组 　　&nbsp;&nbsp; &nbsp; &nbsp; |<br />
&nbsp;| double[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jdoubleArray&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 双浮点型数组&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; |<br />
&nbsp;+---------------+--------------------+--------------------------+<br />
<br />
※ JNI类型映射<br />
最后一步是把本地代码编译成共享库（比如，UNIX的so文件，Windows的dll文件）。在Java中调用方法前，共享库须通过System.loadLibrary导入。<br />
最常用的方式是在类的静态（static）初始化器里做这这个工作。<br />
<br />
在本地代码中访问JNI我举的例子很简单，并不能满足演示怎样写JNI方法的目标。现在，让我们看一些高级的，通过JNIEnv结构使用非简单类型的例子。<br />
<br />
JNI通过函数的形式提供了很多功能，供本地代码通过指向JNIEnv结构的指针调用；它作为第一个参数传递给每个本地方法。JNI函数的调用有下面<br />
几种格式（这里，假设env是指向JNIEnv的指针）：<br />
<br />
//C 格式<br />
<br />
(*env)-＞＜jni function＞( env, ＜parameters＞ )<br />
<br />
//C++ 格式<br />
<br />
env-＞＜jni function＞( ＜ parameters＞ )<br />
<br />
这篇文章中接下来的例子我将会用C++格式。<br />
<br />
使用数组：<br />
JNI通过JNIEnv提供的操作Java数组的功能。它提供了两个函数：一个是操作java的简单<br />
型数组的，另一个是操作对象类型数组的。<br />
因为速度的原因，简单类型的数组作为指向本地类型的指针暴露给本地代码。因此，它<br />
们能作为常规的数组存取。这个指针是指向实际的Java数组或者Java数组的拷贝的指针。另<br />
外，数组的布置保证匹配本地类型。<br />
为了存取Java简单类型的数组，你就要要使用GetXXXArrayElements函数（见表B），XX<br />
X代表了数组的类型。这个函数把Java数组看成参数，返回一个指向对应的本地类型的数组的<br />
指针。<br />
<br />
<br />
表B 　<br />
<br />
&nbsp; 函数&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Java数组类型&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 本地类型 <br />
+--------------------------+---------------------+-----------------+&nbsp; 　　<br />
|<u> GetBooleanArrayElements&nbsp; |&nbsp;&nbsp;&nbsp; jbooleanArray&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jboolean 　　</u>|<br />
|<u> GetByteArrayElements&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jbyteArray&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jbyte 　　&nbsp;&nbsp; </u>|&nbsp;&nbsp;&nbsp; <br />
|<u> GetCharArrayElements&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jcharArray&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jchar 　　&nbsp;&nbsp; </u>|<br />
|<u> GetShortArrayElements&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jshortArray&nbsp;&nbsp;&nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; jshort&nbsp; &nbsp; &nbsp;&nbsp; </u>|<br />
|<u> GetIntArrayElements&nbsp;&nbsp;&nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; jintArray&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jint 　　&nbsp;&nbsp;&nbsp; </u>|<br />
|<u> GetLongArrayElements&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jlongArray&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jlong&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </u>|<br />
|<u> GetFloatArrayElements&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jfloatArray&nbsp;&nbsp;&nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; jfloat 　　&nbsp; </u>|<br />
|<u> GetDoubleArrayElements&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jdoubleArray&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; jdouble&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </u>|<br />
<br />
JNI数组存取函数<br />
当你对数组的存取完成后，要确保调用相应的ReleaseXXXArrayElements函数，参数是对应Java数组和 GetXXXArrayElements返回的指针。<br />
如果必要的话，这个释放函数会复制你做的任何变化（这样它们就反射到java数组），然后释放所有相关的资源。<br />
<br />
为了使用java对象的数组，你必须使用GetObjectArrayElement函数和SetObjectArrayElement函数，分别去get，set数组的元素。<br />
GetArrayLength函数会返回数组的长度。<br />
<br />
&nbsp;&nbsp;&nbsp; 清单D包含了一个简单的类，它演示了本地代码如何使用Java数组。这个本地实现循环遍历一个整型（int）数组，返回这些元素的总和。<br />
为简单起见，这个清单包含了java代码和本地实现。我已经省略了头文件，它可以很方便地通过javah得到。<br />
<br />
<br />
在本地代码中访问JNI 　　使用对象<br />
<br />
&nbsp;&nbsp;&nbsp; JNI 提供的另外一个功能是在本地代码中使用Java对象。通过使用合适的JNI函数，你可以创建Java对象，get、set 静态(static)和<br />
实例（instance）的域，调用静态(static)和实例（instance）函数。JNI通过ID识别域和方法，一个域或方法的ID是任何处理域和方法的函数的必须参数。<br />
<br />
表C列出了用以得到静态(static)和实例（instance）的域与方法的JNI函数。每个函数接受（作为参数）域或方法的类，它们的名称，符号和<br />
它们对应返回的jfieldID或jmethodID。<br />
<br />
表C 　<br />
<br />
&nbsp; 函数&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 描述 <br />
+--------------------+---------------------------+　　<br />
|<u>&nbsp; GetFieldID&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 得到一个实例的域的ID 　</u>|　<br />
|<u>&nbsp; GetStaticFieldID&nbsp; |&nbsp;&nbsp;&nbsp; 得到一个静态的域的ID 　</u>|　<br />
|<u>&nbsp; GetMethodID&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 得到一个实例的方法的ID </u>|<br />
|<u>　GetStaticMethodID |&nbsp;&nbsp;&nbsp; 得到一个静态方法的ID&nbsp;&nbsp; </u>|<br />
<br />
<br />
※域和方法的函数<br />
如果你有了一个类的实例，它就可以通过方法GetObjectClass得到，或者如果你没有这个类的实例，可以通过FindClass得到。符号是从域的类型或者<br />
方法的参数，返回值得到字符串，如表D所示。<br />
<br />
表D <br />
&nbsp;&nbsp; +------------+---------+<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |Java 类型&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 符号 |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +------------+---------+　　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |boolean&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; Z 　 |　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |byte&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; B 　 |　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |char&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; C 　 |　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |short&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; S&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |int&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; I&nbsp;&nbsp;&nbsp; |　　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |long&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; L&nbsp;&nbsp;&nbsp; |　　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |float&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; F&nbsp;&nbsp;&nbsp; |　　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |double&nbsp; &nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; D&nbsp;&nbsp;&nbsp; |　　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |void&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; V&nbsp;&nbsp;&nbsp; |　　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |objects对象 |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +------------+---------+<br />
<br />
&nbsp;&nbsp;&nbsp; Lfully-qualified-class-name;L类名 　　<br />
&nbsp;&nbsp;&nbsp; Arrays数组 [array-type [数组类型 methods方法 (argument-types)return-type(参数类型)返回类型<br />
<br />
<br />
※确定域和方法的符号<br />
<br />
一旦你有了类和方法或者域的ID，你就能把它保存下来以后使用，而没有必要重复去获取。<br />
<br />
有几个分别访问域和方法的函数。实例的域可以使用对应域的GetXXXField的变体函数访问。GetStaticXXXField函数用于静态类型。<br />
设置域的值，用SetXXXField 和SetStaticXXXField函数。表E包含了所有访问域的函数列表。<br />
<br />
表E 　　<br />
&nbsp; +-------------+---------------------------+ <br />
&nbsp; |&nbsp; Java类型&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; Method方法&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; +-------------+---------------------------+　　<br />
&nbsp; |&nbsp;&nbsp; boolean&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetBooleanField &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetStaticBooleanField&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetBooleanField &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetStaticBooleanField&nbsp; |<br />
&nbsp; +-------------+---------------------------+　<br />
&nbsp; |&nbsp;&nbsp; byte&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetByteField&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetStaticByteField&nbsp; &nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetByteField&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetStaticByteField 　　|<br />
&nbsp; +-------------+---------------------------+<br />
&nbsp; |&nbsp;&nbsp; char&nbsp;&nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetCharField&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetStaticCharField&nbsp; &nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetCharField&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetStaticCharField 　　|<br />
&nbsp; +-------------+---------------------------+<br />
&nbsp; |&nbsp;&nbsp; short&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetShortField&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetStaticShortField&nbsp; &nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetShortField&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; SetStaticShortField 　 |　<br />
&nbsp; +-------------+---------------------------+<br />
&nbsp; |&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetIntField,&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetStaticIntField,&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetIntField,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetStaticIntField 　&nbsp;&nbsp; |<br />
&nbsp; +-------------+---------------------------+<br />
&nbsp; |&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetLongField,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetStaticLongField,&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetLongField,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetStaticLongField 　&nbsp; |<br />
&nbsp; +-------------+---------------------------+<br />
&nbsp; |&nbsp;&nbsp; float&nbsp;&nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; GetFloatField,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetStaticFloatField,&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetFloatField,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetStaticFloatField&nbsp;&nbsp;&nbsp; |<br />
&nbsp; +-------------+---------------------------+<br />
&nbsp; |　double&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetDoubleField,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; GetStaticDoubleField,&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; SetDoubleField,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; |&nbsp;&nbsp;&nbsp; SetStaticDoubleField 　|　<br />
&nbsp; +-------------+---------------------------+<br />
&nbsp; |&nbsp; object&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetObjectField,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; GetStaticObjectField,&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetObjectField,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; SetStaticObjectField&nbsp;&nbsp; |<br />
&nbsp; +-------------+---------------------------+<br />
<br />
※访问域的函数<br />
&nbsp;&nbsp;&nbsp; 另外，方法的访问是由 CallXXXMethod 函数和 CallStaticXXXMethod函数完成的，XXX表明了方法的返回值类型。这些函数的变体允<br />
许传递数组参数 (CallXXXMethodA and CallStaticXXXMethodA)或者传递一个可变大小的列表(CallXXXMethodV and CallStaticXXXMethodV)。<br />
<br />
<br />
一个完整的列表<br />
<br />
表F：一个完整的列表 　<br />
<br />
&nbsp;&nbsp;&nbsp; 返回类型&nbsp;&nbsp;&nbsp; 函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-------------+---------------------------+　　&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; boolean&nbsp; |&nbsp; CallBooleanMethod&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallBooleanMethodA&nbsp; &nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallBooleanMethodV&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticBooleanMethod&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticBooleanMethodA |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; |&nbsp; CallStaticBooleanMethodV |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-------------+---------------------------+<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; byte&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallByteMethod&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallByteMethodA &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallByteMethodV&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticByteMethod&nbsp; &nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticByteMethodA&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticByteMethodV&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-------------+---------------------------+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 　　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; char&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallCharMethod&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallCharMethodA&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallCharMethodV&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticCharMethod &nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticCharMethodA&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticCharMethodV　&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-------------+---------------------------+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; short&nbsp;&nbsp;&nbsp; |&nbsp; CallShortMethod &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallShortMethodA&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallShortMethodV&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticShortMethod&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticShortMethodA &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticShortMethodV &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-------------+---------------------------+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallIntMethod &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallIntMethodA&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallIntMethodV&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticIntMethod&nbsp; &nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticIntMethodA&nbsp; &nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticIntMethodV 　&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-------------+---------------------------+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallLongMethod&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallLongMethodA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallLongMethodV&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticLongMethod&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticLongMethodA&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticLongMethodV　&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-------------+---------------------------+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; float&nbsp;&nbsp;&nbsp; |&nbsp; CallFloatMethod &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallFloatMethodA &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallFloatMethodV &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticFloatMethod&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticFloatMethodA&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticFloatMethodV&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-------------+---------------------------+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 　　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; double&nbsp;&nbsp; |&nbsp; CallDoubleMethod &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallDoubleMethodA &nbsp; &nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallDoubleMethodV &nbsp; &nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticDoubleMethod&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticDoubleMethodA&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticDoubleMethodV　|<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-------------+---------------------------+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | void&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; |&nbsp; CallVoidMethod&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallVoidMethodA &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallVoidMethodV &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticVoidMethod&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; |&nbsp; CallStaticVoidMethodA&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; |&nbsp; CallStaticVoidMethodV&nbsp; &nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-------------+---------------------------+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 　　<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | object&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallObjectMethod&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallObjectMethodA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallObjectMethodV&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticObjectMethod&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticObjectMethodA&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; CallStaticObjectMethodV&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-------------+---------------------------+<br />
<br />
当你关注java的扩展时，JNI是一个强大的工具，它不会严重降低可移植性。我这里只是接触它的表面，仅仅向你演示了JNI的能力和潜力。我鼓励你获取 　　<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/hyint/aggbug/258623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hyint/" target="_blank">苦瓜</a> 2009-03-09 16:59 <a href="http://www.blogjava.net/hyint/articles/258623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JNI  ------ Java Native Interface (Java 本地接口)</title><link>http://www.blogjava.net/hyint/articles/258613.html</link><dc:creator>苦瓜</dc:creator><author>苦瓜</author><pubDate>Mon, 09 Mar 2009 08:18:00 GMT</pubDate><guid>http://www.blogjava.net/hyint/articles/258613.html</guid><wfw:comment>http://www.blogjava.net/hyint/comments/258613.html</wfw:comment><comments>http://www.blogjava.net/hyint/articles/258613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hyint/comments/commentRss/258613.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hyint/services/trackbacks/258613.html</trackback:ping><description><![CDATA[<meta content="Word.Document" name="ProgId" />
<meta content="Microsoft Word 11" name="Generator" />
<meta content="Microsoft Word 11" name="Originator" />
<link href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml" rel="File-List" /><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:PunctuationKerning/>
<w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:SpaceForUL/>
<w:BalanceSingleByteDoubleByteWidth/>
<w:DoNotLeaveBackslashAlone/>
<w:ULTrailSpace/>
<w:DoNotExpandShiftReturn/>
<w:AdjustLineHeightInTable/>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:UseFELayout/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
</w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles deflockedstate="false" latentstylecount="156">
</w:LatentStyles>
</xml><![endif]-->
<style>
<!-- /* Font Definitions */
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;
mso-font-charset:2;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:0 268435456 0 0 -2147483648 0;}
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"\@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
p
{mso-margin-top-alt:auto;
margin-right:0cm;
mso-margin-bottom-alt:auto;
margin-left:0cm;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:宋体;
mso-bidi-font-family:宋体;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:595.3pt 841.9pt;
margin:54.55pt 46.3pt 72.0pt 45.0pt;
mso-header-margin:42.55pt;
mso-footer-margin:49.6pt;
mso-paper-source:0;
layout-grid:15.6pt;}
div.Section1
{page:Section1;}
/* List Definitions */
@list l0
{mso-list-id:44531681;
mso-list-template-ids:1151265196;}
@list l0:level1
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:36.0pt;
mso-level-number-position:left;
text-indent:-18.0pt;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
@list l1
{mso-list-id:51585350;
mso-list-template-ids:1328175036;}
@list l1:level1
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:36.0pt;
mso-level-number-position:left;
text-indent:-18.0pt;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
@list l2
{mso-list-id:703135797;
mso-list-template-ids:935254178;}
@list l2:level1
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:36.0pt;
mso-level-number-position:left;
text-indent:-18.0pt;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
@list l3
{mso-list-id:758791968;
mso-list-template-ids:-1058773756;}
@list l3:level1
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:36.0pt;
mso-level-number-position:left;
text-indent:-18.0pt;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
@list l4
{mso-list-id:795216359;
mso-list-template-ids:296811844;}
@list l4:level1
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:36.0pt;
mso-level-number-position:left;
text-indent:-18.0pt;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
@list l5
{mso-list-id:1063210938;
mso-list-template-ids:-1352872398;}
@list l5:level1
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:36.0pt;
mso-level-number-position:left;
text-indent:-18.0pt;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
@list l6
{mso-list-id:2054189778;
mso-list-template-ids:320640154;}
@list l6:level1
{mso-level-number-format:bullet;
mso-level-text:;
mso-level-tab-stop:36.0pt;
mso-level-number-position:left;
text-indent:-18.0pt;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
ol
{margin-bottom:0cm;}
ul
{margin-bottom:0cm;}
-->
</style>
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";
mso-ansi-language:#0400;
mso-fareast-language:#0400;
mso-bidi-language:#0400;}
</style>
<![endif]-->
<p class="MsoNormal"><span style="font-size: 15pt; font-family: 宋体">一．</span><span lang="EN-US" style="font-size: 15pt">JNI</span><span style="font-size: 15pt; font-family: 宋体">简介</span><span lang="EN-US" style="font-size: 15pt"><o:p></o:p></span></p>
<p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 14pt">1</span></strong><strong><span style="font-size: 14pt; font-family: 宋体">．开篇</span></strong><strong><span lang="EN-US" style="font-size: 14pt"><o:p></o:p></span></strong></p>
<p style="margin: 0cm 0cm 0pt; line-height: 18pt">　　<span lang="EN-US" style="font-size: 10.5pt">JNI </span><span style="font-size: 10.5pt">是本地编程接口。它使得在<span lang="EN-US"> Java </span>虚拟机<span lang="EN-US"> (VM) </span>内部运行的<span lang="EN-US"> Java </span>代码能够与用其它编程语言（如<span lang="EN-US"> C</span>、<span lang="EN-US">C++ </span>和汇编语言）编写的应用程序和库进行互操作。<span lang="EN-US"><o:p></o:p></span></span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt; line-height: 18pt"><span lang="EN-US" style="font-size: 10.5pt">JNI </span><span style="font-size: 10.5pt">最重要的好处是它没有对底层<span lang="EN-US"> Java </span>虚拟机的实现施加任何限制。因此，<span lang="EN-US">Java </span>虚拟机厂商可以在不影响虚拟机其它部分的情况下添加对<span lang="EN-US"> JNI </span>的支持。程序员只需编写一种版本的本地应用程序或库，就能够与所有支持<span lang="EN-US"> JNI </span>的<span lang="EN-US"> Java </span>虚拟机协同工作。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-indent: 12pt"><span lang="EN-US" style="font-size: 12pt">1.1 </span><span style="font-size: 12pt; font-family: 宋体">为什么需要</span><span lang="EN-US" style="font-size: 12pt">JNI</span><span style="font-size: 12pt; font-family: 宋体">？</span><span lang="EN-US" style="font-size: 12pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 10.5pt"><span lang="EN-US"><span>&nbsp; </span>Java</span><span style="font-family: 宋体">是跨平台的语言，但是有的时候需要调用本地代码实现升级，更新或者其他操作，而这些本地代码往往是一个</span><span lang="EN-US">COM</span><span style="font-family: 宋体">技术编程，生成的</span><span lang="EN-US">DLL</span><span style="font-family: 宋体">是与本机密切关联着的，这时我们就需要</span><span lang="EN-US">JNI</span><span style="font-family: 宋体">来调用本地的</span><span lang="EN-US">dll</span><span style="font-family: 宋体">文件。</span></p>
<p class="MsoNormal" style="text-indent: 12pt"><span lang="EN-US" style="font-size: 12pt">1.2 </span><span style="font-size: 12pt; font-family: 宋体">什么是</span><span lang="EN-US" style="font-size: 12pt">JNI</span><span style="font-size: 12pt; font-family: 宋体">？</span><span lang="EN-US" style="font-size: 12pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 10.5pt"><span lang="EN-US"><span>&nbsp; </span>SUN</span><span style="font-family: 宋体">公司提供的</span><span lang="EN-US">JNI</span><span style="font-family: 宋体">是</span><span lang="EN-US">Java</span><span style="font-family: 宋体">平台的一个功能强大的接口，这个</span><span lang="EN-US">JNI</span><span style="font-family: 宋体">提供了</span><span lang="EN-US">Java</span><span style="font-family: 宋体">与操作系统本地代码交互调用的功能。</span></p>
<p class="MsoNormal"><strong><span lang="EN-US" style="font-size: 14pt">2 . Java</span></strong><strong><span style="font-size: 14pt; font-family: 宋体">本地接口概述</span></strong><strong><span lang="EN-US" style="font-size: 14pt"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">尽管可以完全用<span lang="EN-US"> Java </span>编写应用程序，但是有时单独用<span lang="EN-US"> Java </span>不能满足应用程序的需要。程序员使用<span lang="EN-US"> JNI </span>来编写 <em><span lang="EN-US">Java </span>本地方法</em>，可以处理那些不能完全用<span lang="EN-US"> Java </span>编写应用程序的情况。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;以下示例说明了何时需要使用<span lang="EN-US"> Java </span>本地方法：<span lang="EN-US"> <o:p></o:p></span></span></p>
<ul style="margin-top: 0cm" type="disc">
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">标准<span lang="EN-US"> Java </span>类库不支持与平台相关的应用程序所需的功能。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">已经拥有了一个用另一种语言编写的库，而又希望通过<span lang="EN-US"> JNI </span>使<span lang="EN-US"> Java </span>代码能够访问该库。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">想用低级语言（如汇编语言）实现一小段时限代码。<span lang="EN-US"> <o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">通过用<span lang="EN-US"> JNI </span>编程，可以将本地方法用于：<span lang="EN-US"> <o:p></o:p></span></span></p>
<ul style="margin-top: 0cm" type="disc">
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">创建、检查及更新<span lang="EN-US"> Java </span>对象（包括数组和字符串）。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">调用<span lang="EN-US"> Java </span>方法。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">捕捉和抛出异常。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">加载类和获得类信息。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">执行运行时类型检查。<span lang="EN-US"> <o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp; 也可以与<em>调用<span lang="EN-US"> API</span></em><span lang="EN-US"> </span>一起使用<span lang="EN-US"> JNI</span>，以允许任意本地应用程序嵌入到<span lang="EN-US"> Java </span>虚拟机中。这样使得程序员能够轻易地让已有应用程序支持<span lang="EN-US"> Java</span>，而不必与虚拟机源代码相链接。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left" align="left"><strong><span lang="EN-US" style="font-size: 14pt; font-family: 宋体">3.</span></strong><strong><span style="font-size: 14pt; font-family: 宋体">背景<span lang="EN-US"> <o:p></o:p></span></span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">目前，不同厂商的虚拟机提供了不同的本地方法接口。这些不同的接口使程序员不得不在给定平台上编写、维护和分发多种版本的本地方法库。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">下面简要分析一下部分已有本地方法接口，例如：<span lang="EN-US"> <o:p></o:p></span></span></p>
<p class="MsoNormal" style="margin-left: 35.7pt; text-indent: -17.85pt; line-height: 18pt; text-align: left" align="left"><!--[if !supportLists]--><span lang="EN-US" style="font-size: 10pt; font-family: Symbol"><span>&#183;<span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal; -x-system-font: none">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]--><span lang="EN-US" style="font-family: 宋体">JDK 1.0 </span><span style="font-family: 宋体">本地方法接口<span lang="EN-US"> <o:p></o:p></span></span></p>
<p class="MsoNormal" style="margin-left: 35.7pt; text-indent: -17.85pt; line-height: 18pt; text-align: left" align="left"><!--[if !supportLists]--><span lang="EN-US" style="font-size: 10pt; font-family: Symbol"><span>&#183;<span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal; -x-system-font: none">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]--><span lang="EN-US" style="font-family: 宋体">Netscape </span><span style="font-family: 宋体">的<span lang="EN-US"> Java </span>运行时接口<span lang="EN-US"> <o:p></o:p></span></span></p>
<p class="MsoNormal" style="margin-left: 35.7pt; text-indent: -17.85pt; line-height: 18pt; text-align: left" align="left"><!--[if !supportLists]--><span lang="EN-US" style="font-size: 10pt; font-family: Symbol"><span>&#183;<span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal; -x-system-font: none">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]--><span lang="EN-US" style="font-family: 宋体">Microsoft </span><span style="font-family: 宋体">的原始本地接口和<span lang="EN-US"> Java/COM </span>接口 <span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="line-height: 18pt; text-align: left" align="left"><strong><span lang="EN-US" style="font-size: 14pt; font-family: 宋体">4.JDK 1.0 </span></strong><strong><span style="font-size: 14pt; font-family: 宋体">本地方法接口<span lang="EN-US"> <o:p></o:p></span></span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 18pt; text-align: left" align="left"><span lang="EN-US" style="font-family: 宋体">JDK 1.0 </span><span style="font-family: 宋体">附带有本地方法接口。遗憾的是<span lang="EN-US">,</span>有两点原因使得该接口不适合于其它<span lang="EN-US"> Java </span>虚拟机。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">第一，平台相关代码将<span lang="EN-US"> Java </span>对象中的域作为<span lang="EN-US"> C </span>结构的成员来进行访问。但是，<em><span lang="EN-US">Java </span>语言规范</em>没有规定在内存中对象是如何布局的。如果<span lang="EN-US"> Java </span>虚拟机在内存中布局对象的方式有所不同，程序员就不得不重新编译本地方法库。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">第二，<span lang="EN-US">JDK 1.0 </span>的本地方法接口依赖于保守的垃圾收集器。例如，无限制地使用<span lang="EN-US"> unhand </span>宏使得有必要以保守方式扫描本地堆栈。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left" align="left"><strong><span lang="EN-US" style="font-size: 14pt; font-family: 宋体">5.Java </span></strong><strong><span style="font-size: 14pt; font-family: 宋体">运行时接口<span lang="EN-US"> <o:p></o:p></span></span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 18pt; text-align: left" align="left"><span lang="EN-US" style="font-family: 宋体">Netscape </span><span style="font-family: 宋体">建议使用<span lang="EN-US"> Java </span>运行时接口<span lang="EN-US"> (JRI)</span>，它是<span lang="EN-US"> Java </span>虚拟机所提供服务的通用接口。<span lang="EN-US">JRI </span>的设计融入了可移植性<span lang="EN-US">---</span>它几乎没有对底层<span lang="EN-US"> Java </span>虚拟机的实现细节作任何假设。<span lang="EN-US">JRI </span>提出了各种各样的问题，包括本地方法、调试、反射、嵌入（调用）等等。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left" align="left"><strong><span lang="EN-US" style="font-size: 14pt; font-family: 宋体">6.</span></strong><strong><span style="font-size: 14pt; font-family: 宋体">原始本地接口和<span lang="EN-US"> Java/COM </span>接口<span lang="EN-US"> <o:p></o:p></span></span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 18pt; text-align: left" align="left"><span lang="EN-US" style="font-family: 宋体">Microsoft Java </span><span style="font-family: 宋体">虚拟机支持两种本地方法接口。在低一级，它提供了高效的原始本地接口<span lang="EN-US"> (RNI)</span>。<span lang="EN-US">RNI </span>提供了与<span lang="EN-US"> JDK </span>本地方法接口有高度源代码级的向后兼容性，尽管它们之间还有一个主要区别，即平台相关代码必须用<span lang="EN-US"> RNI </span>函数来与垃圾收集器进行显式的交互，而不是依赖于保守的垃圾收集。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">在高一级，<span lang="EN-US">Microsoft </span>的<span lang="EN-US"> Java/COM </span>接口为<span lang="EN-US"> Java </span>虚拟机提供了与语言无关的标准二进制接口。<span lang="EN-US">Java </span>代码可以象使用<span lang="EN-US"> Java </span>对象一样来使用<span lang="EN-US"> COM </span>对象。<span lang="EN-US">Java </span>类也可以作为<span lang="EN-US"> COM </span>类显示给系统的其余部分。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left" align="left"><strong><span lang="EN-US" style="font-size: 14pt; font-family: 宋体">7.</span></strong><strong><span style="font-size: 14pt; font-family: 宋体">目标<span lang="EN-US"> <o:p></o:p></span></span></strong></p>
<p class="MsoNormal" style="line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">我们认为统一的，经过细致考虑的标准接口能够向每个用户提供以下好处：<span lang="EN-US"> <o:p></o:p></span></span></p>
<ul style="margin-top: 0cm" type="disc">
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">每个虚拟机厂商都可以支持更多的平台相关代码。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">工具构造器不必维护不同的本地方法接口。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">应用程序设计人员可以只编写一种版本的平台相关代码就能够在不同的虚拟机上运行。<span lang="EN-US"> <o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp; 获得标准本地方法接口的最佳途径是联合所有对<span lang="EN-US"> Java </span>虚拟机有兴趣的当事方。因此，我们在<span lang="EN-US"> Java </span>获得许可方之间组织了一系列研讨会，对设计统一的本地方法接口进行了讨论。从研讨会可以明确地看出标准本地方法接口必须满足以下要求：<span lang="EN-US"> <o:p></o:p></span></span></p>
<ul style="margin-top: 0cm" type="disc">
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">二进制兼容性<span lang="EN-US"> - </span>主要的目标是在给定平台上的所有<span lang="EN-US"> Java </span>虚拟机实现之间实现本地方法库的二进制兼容性。对于给定平台，程序员只需要维护一种版本的本地方法库。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">效率<span lang="EN-US"> - </span>若要支持时限代码，本地方法接口必须增加一点系统开销。所有已知的用于确保虚拟机无关性（因而具有二进制兼容性）的技术都会占用一定的系统开销。我们必须在效率与虚拟机无关性之间进行某种折衷。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">功能<span lang="EN-US"> - </span>接口必须显示足够的<span lang="EN-US"> Java </span>虚拟机内部情况以使本地方法能够完成有用的任务。<span lang="EN-US"><o:p></o:p></span></span> </li>
</ul>
<p class="MsoNormal" style="text-align: left" align="left"><strong><span lang="EN-US" style="font-size: 14pt; font-family: 宋体">&nbsp;&nbsp; 8.</span></strong><strong><span lang="EN-US" style="font-size: 14pt; font-family: 宋体">Java </span></strong><strong><span style="font-size: 14pt; font-family: 宋体">本地接口方法 <span lang="EN-US"><o:p></o:p></span></span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt; text-align: left" align="left"><span style="font-family: 宋体">我们希望采用一种已有的方法作为标准接口，因为这样程序员（程序员不得不学习在不同虚拟机中的多种接口）的工作负担最轻。遗憾的是，已有解决方案中没有任何方案能够完全地满足我们的目标。<span lang="EN-US">Netscape </span>的<span lang="EN-US"> JRI </span>最接近于我们所设想的可移植本地方法接口，因而我们采用它作为设计起点。熟悉<span lang="EN-US"> JRI </span>的读者将会注意到在<span lang="EN-US"> API </span>命名规则、方法和域<span lang="EN-US"> ID </span>的使用、局部和全局引用的使用，等等中的相似点。虽然我们进行了最大的努力，但是<span lang="EN-US"> JNI </span>并不具有对<span lang="EN-US"> JRI </span>的二进制兼容性，不过虚拟机既可以支持<span lang="EN-US"> JRI</span>，又可以支持<span lang="EN-US"> JNI</span>。</span><strong><span lang="EN-US" style="font-family: 宋体"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="line-height: 18pt; text-align: left" align="left"><span lang="EN-US" style="font-family: 宋体">&nbsp;&nbsp;&nbsp; Microsoft </span><span style="font-family: 宋体">的<span lang="EN-US"> RNI </span>是对<span lang="EN-US"> JDK 1.0 </span>的改进，因为它可以解决使用非保守的垃圾收集器的本地方法的问题。然而，<span lang="EN-US">RNI </span>不适合用作与虚拟机无关的本地方法接口。与<span lang="EN-US"> JDK </span>类似，<span lang="EN-US">RNI </span>本地方法将<span lang="EN-US"> Java </span>对象作为<span lang="EN-US"> C </span>结构来访问。这将导致两个问题：<span lang="EN-US"> <o:p></o:p></span></span></p>
<ul style="margin-top: 0cm" type="disc">
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span lang="EN-US" style="font-family: 宋体">RNI </span><span style="font-family: 宋体">将内部<span lang="EN-US"> Java </span>对象的布局暴露给了平台相关代码。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">将<span lang="EN-US"> Java </span>对象作为<span lang="EN-US"> C </span>结构直接进行访问使得不可能有效地加入<span lang="EN-US">&#8220;</span>写屏障<span lang="EN-US">&#8221;</span>，写屏障是高级的垃圾收集算法所必需的。<span lang="EN-US"> <o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp; 作为二进制标准，<span lang="EN-US">COM </span>确保了不同虚拟机之间的完全二进制兼容性。调用<span lang="EN-US"> COM </span>方法只要求间接调用，而这几乎不会占用系统开销。另外，<span lang="EN-US">COM </span>对象对动态链接库解决版本问题的方式也有很大的改进。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;然而，有几个因素阻碍了将<span lang="EN-US"> COM </span>用作标准<span lang="EN-US"> Java </span>本地方法接口：<span lang="EN-US"> <o:p></o:p></span></span></p>
<ul style="margin-top: 0cm" type="disc">
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">第一，<span lang="EN-US">Java/COM </span>接口缺少某些必需功能，例如访问私有域和抛出普通异常。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">第二，<span lang="EN-US">Java/COM </span>接口自动为<span lang="EN-US"> Java </span>对象提供标准的<span lang="EN-US"> IUnknown </span>和<span lang="EN-US"> IDispatch COM </span>接口，因而平台相关代码能够访问公有方法和域。遗憾的是，<span lang="EN-US">IDispatch </span>接口不能处理重载的<span lang="EN-US"> Java </span>方法，而且在匹配方法名称时不区别大小写。另外，通过<span lang="EN-US"> IDispatch </span>接口暴露的所有<span lang="EN-US"> Java </span>方法被打包在一起来执行动态类型检查和强制转换。这是因为<span lang="EN-US"> IDispatch </span>接口的设计只考虑到了弱类型的语言（例如<span lang="EN-US"> Basic</span>）。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">第三，<span lang="EN-US">COM </span>允许软件组件（包括完全成熟的应用程序）一起工作，而不是处理单个低层函数。我们认为将所有<span lang="EN-US"> Java </span>类或低层本地方法都当作软件组件是不恰当的。<span lang="EN-US"> <o:p></o:p></span></span>
    <li class="MsoNormal" style="line-height: 18pt; text-align: left"><span style="font-family: 宋体">第四，在<span lang="EN-US"> UNIX </span>平台上由于缺少对<span lang="EN-US"> COM </span>的支持，所以阻碍了直接采用<span lang="EN-US"> COM</span>。<span lang="EN-US"> <o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp; 虽然我们没有将<span lang="EN-US"> Java </span>对象作为<span lang="EN-US"> COM </span>对象暴露给平台相关代码，但是<span lang="EN-US"> JNI </span>接口自身与<span lang="EN-US"> COM </span>具有二进制兼容性。我们采用与<span lang="EN-US"> COM </span>一样的跳转表和调用约定。<em>这意味着，一旦具有对<span lang="EN-US"> COM </span>的跨平台支持，<span lang="EN-US">JNI </span>就能成为<span lang="EN-US"> Java </span>虚拟机的<span lang="EN-US"> COM </span>接口。</em><span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-indent: 18.4pt; line-height: 18pt; text-align: left" align="left"><span style="font-family: 宋体">我们认为<span lang="EN-US"> JNI </span>不应该是给定<span lang="EN-US"> Java </span>虚拟机所支持的唯一的本地方法接口。标准接口的好处在于程序员可以将自己的平台相关代码库加载到不同的<span lang="EN-US"> Java </span>虚拟机上。在某些情况下，程序员可能不得不使用低层且与虚拟机有关的接口来获得较高的效率。但在其它情况下，程序员可能使用高层接口来建立软件组件。实际上，我们希望随着<span lang="EN-US"> Java </span>环境和组件软件技术发展得越来越成熟，本地方法将变得越来越不重要。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-indent: 10.5pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 10.5pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 10.5pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<img src ="http://www.blogjava.net/hyint/aggbug/258613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hyint/" target="_blank">苦瓜</a> 2009-03-09 16:18 <a href="http://www.blogjava.net/hyint/articles/258613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>