原文链接:http://blog.sina.com.cn/s/blog_53988c0c0100ospm.html
第十二章"JNI"类型
这章详细说明(specify)被"JNI"定义的标准数据类型。在引用这些类型前,"C and C++"代码应该包含头文件"jni.h"。
12.1 基本的引用类型(Primitive and Reference Types)
"JNI"定义C/C++类型的集合对应在"Java"编程语言中基本的引用类型。
12.1.1 基本类型(Primitive Types)
下面的表详细描述在"Java"编程语言中基本类型和在"JNI"中的对应的类型。像在"Java"编程语言中它们的配对物,在"JNI"中所有的基本类型有定义好的(well-defined)大小(sizes)。
Java Language Type
boolean
byte
char
short
int
long
float
double
"jsize"整数类型被用来描述基数的指标和大小(cardinal indices and sizes):
typedef jint jsize ;
12.1.2 引用的类型(Reference Types)
"JNI"包含一组引用类型,对应在"Java"编程中不同类别的引用类型。在继承关系中组织"JNI"引用类型显示如下(show below)
jobject
当在"C"编程语言中使用引用类型时,所有其他JNI引用类型被定义为和"jobject"一样的。例如:
typedef jobject jclass;
当在"C++"编程语言中使用引用类型时,"JNI"介绍了一组空类集合来表带子类的关系在各种引用类之间:
class _jobject{} ;
class _jclass: public _jobject{} ;
class _jthrowable:public _jobject{} ;
class _jstring:public _jobject{} ;
class _jarray:public _jobject{} ;
class _jbooleanArray:public _jarray{} ;
class _jbyteArray:public _jarray{} ;
class _jcharArray:public _jarray{} ;
class _jshortArray:public _jarray{} ;
class _jintArray:public _jarray{} ;
class _jlongArray:public _jarray{} ;
class _jfloatArray:public _jarray{} ;
class _jdoubleArray:public _jarray{} ;
class _jobjectArray:public _jarray{} ;
typedef _jobject *jobject ;
typedef _jclass *jclass ;
typedef _jthrowable *jthrowable ;
typedef _jstring *jstring ;
typedef _jarray *jarray ;
typedef _jbooleanArray *jbooleanArray ;
typedef _jbyteArray *jbyteArray ;
typedef _jcharArray *jcharArray ;
typedef _jshortArray *jshortArray ;
typedef _jintArray *jintArray ;
typedef _jlongArray *jlongArray ;
typedef _jfloatArray *jfloatArray ;
typedef _jdoubleArray *jdoubleArray ;
typedef _jobjectArray *jobjectArray ;
12.1.3 "jvalue"类型(The jvalue Type)
"jvalue"类型是一个引用类型和基本类型的联合体。定义如下:
typedef union jvalue{
}jvalue ;
12.2 成员域和方法IDs(Field and Method IDs)
方法和成员域IDs是规则的"C"指针类型:
struct _jfieldID ;
typedef struct _jfieldID *jfieldID ;
struct _jmethodID ;
typedef struct _jmethodID *jmethodID ;
12.3 字符串格式(String Formats)
"JNI"使用"C"字符串来表示类名字,成员域和方法名字,和成员域和方法的描述。这些字符串是"UTF-8"格式。
12.3.1 UTF-8字符串(UTF-8 Strings)
"UTF-8"字符串被编码,使包含非空"ASCII"码的字符串序列能够被每个字符只适用一个"byte"来表示,但是要表示高达"16 bits"的字符串。在"\u0001"到"\u007f"之间的所有字符都是用单一"byte"来表示的,如下:
|0| bits 6-0 |
在这个"byte"中, 数据的7个"bits"给出了字符代表的值。
空(nulll)字符("\u0000")和在"\u0080"到"\u07ff"之间的字符值是用一对"bytes", x和y,来表示的,如下(as follows):
x: |1|1|0| bits 10-6 |
"byts"用( (x&1f)<<6)+(y&0x3f) )的值来表示字符。
在"\u0800"到"\uffff"之间的字符用三个byts, x,y和z,来代表:
x:|1|1|1|0| bits 15-12 |
三个"bytes"用( (x&0xf)<<12) + (y&0x3f)<<6 + (z&0x3f) )的值来表示。
这个格式和标准的"UTF-8"格式之间的有两个不同。首先,空(null byte)字符( byte 0)是使用两个byte(two-byte)格式而不是一个byte(one-byte)格式来编码的。这意味"JNI UTF-8"字符串没有嵌入空(0x0000 无效)。第二,只有"one-byte, two-byte and three-byte"三种格式被用。"JNI"不认识更长的"UTF-8"格式。
12.3.2 类的描述(Class Descriptors)
一个类的描述表示一个类或一个接口的名字。通过用"/"字符替代"."字符(by substituting the "." charater with the "/" charater),从用"The Java Langugage Specification"定义的一个完全合格(fully qualified)类或接口来得到它。例如,"java.lang.String"的类的描述符是:
"java/lang/String"
数组类(array classes)是使用后跟元素类型的成员域描述符的"["字符表示的。"int[]"的类描述符是:
"[I"
和"double[][][]"的类描述符是:
"[[[D"
12.3.3 成员域描述符(Field Descriptors)
Field Descriptor
Z
B
C
S
I
J
F
D
引用类型的成员域描述符从"L"字符开始的(begin with),后面跟着类描述符,和以";"字符结束(terminated with)。
数组类型(array types)的成员域描述符的构成,跟数组类(array classes)的类描述符一样的规则。下面(The following are)一些例子,为引用类型成员域描述符和他们"Java"编程语言类型副本。
Field Descriptor
"Ljava/lang/String;"
"[I"
"[Ljava/lang/Object;"
12.3.4 方法描述符(Method Descriptors)
通过在一对括号(parenttheses)中放置所有参数类型的成员域描述符,同时被返回类型成员域描述符跟随,来构成方法描述符。在参数类型之间没有空格或其它隔离字符。"V"被用来指示(denote)"void"方法返回类型。构造器使用"V"作为它们的返回类型,和使用"<init>"作为它们的方法名字。
这儿是"JNI"方法描述符的例子和它们对应的方法和构造器类型。
Method Descriptor
"()Ljava/lang/String;"
"(ILjava/lang/Class;)J"
"([B)V"
12.4 常量(Constants)
"JNIEXPORT"和"JNICALL"是宏,被用来指明"JNI"函数和本地方法实现的调用和链接约定。在函数返回类型前面,程序员必须放置"JNIEXPORT"宏,同时在函数名字和返回类型之间放置"JNICALL"。例如:
JNIEXPORT jint JNICALL
Java_pkg_Cls_f(JNIEnc *env, jobject this) ;
是一个"C"函数的原型,实现了"pkg.Cls.f",然而:
jint (JNICALL *f_ptr)(JNIEnv *env, jobject this) ;
是函数指针变量,它能被赋予"Java_pkg_Cls_f"函数。
"JNI_FALSE"和"JNI_TRUE"是个常数,为"jboolean"类型定义的。
#define JNI_FALSE 0
#define JNI_TRUE 1
"JNI_OK"表示"JNI"函数的成功返回值,同时"JNI_ERR"有时被用来表示错误的情况。
#define JNI_OK 0
#define JNI_ERR (-1)
不是所有的错误情况都用"JNI_ERR"来表示,因为"JNI"规范(specification)当前没有包含一组标准的错误编码。"JNI"函数在成功时返回"JNI_OK",同时在失败时返回一个负数。
下面两个常数被用在释放原始数组的本地副本的函数中。这个函数的一个例子是"ReleaseIntArrayElements"。"JNI_COMMIT"强制本地数组被复制回在"Java"虚拟器中的原始数组中。"JNI_ABORT"释放为本地数组分配的空间,不用复制回新的内容。
#define JNI_COMMIT 1
#define JNI_ABORT 2
"Java 2 SDK release 1.2"介绍两个常量表示"JNI"版本号(version numbers)。
#define JNI_VERSION_1_1 0X00010001
#define JNI_VERSION_1_2 0X00010002
通过执行下面的编译条件,一个本地应用程序可以决定是否编译1.1或1.2版本的"jni.h"文件:
#ifdef JNI_VERSION_1_2
#else
#endif
下面的常量代表"GetEnv"函数返回的详细的错误代码,它是"JavaVM"接口的一部分:
#define JNI_EDETACHED (-2)
#define JNI_EVERSION (-3)