上一篇: 02-设计概述
本章讨论 JNI 如何将 Java 类型映射为本地 C 类型。
3.1 原始类型
下表描述了 Java 原始类型及其与机器相关的本地等价类型。
为方便起见,定义如下:
#define JNI_FALSE 0
#define JNI_TRUE 1
jsize 整数类型用于描述基数索引和大小:
typedef jint jsize;
3.2 引用类型
JNI 包括许多与Java 对象相对应的、不同类型的引用类型。JNI 引用类型按以下层次结构组织:
jobjectjclass (java.lang.Class objects)jstring (java.lang.String objects)jarray (arrays)jobjectArray (object arrays)jbooleanArray (boolean arrays)jbyteArray (byte arrays)jcharArray (char arrays)jshortArray (short arrays)jintArray (int arrays)jlongArray (long arrays)jfloatArray (float arrays)jdoubleArray (double arrays)jthrowable (java.lang.Throwable objects)
在 C 语言中,所有其他 JNI 引用类型的定义都与 jobject 相同。例如:
typedef jobject jclass;
在 C++ 中,JNI 引入了一组假类来执行子类型关系。例如:
class _jobject {};
class _jclass : public _jobject {};
// ...
typedef _jobject *jobject;
typedef _jclass *jclass;
3.3 字段和方法 ID
方法和字段 ID 是常规的 C 指针类型:
struct _jfieldID; /* opaque structure */
typedef struct _jfieldID *jfieldID; /* field IDs */struct _jmethodID; /* opaque structure */
typedef struct _jmethodID *jmethodID; /* method IDs */
3.4 值类型
jvalue 联合类型在参数数组中用作元素类型。其声明如下:
typedef union jvalue {jboolean z;jbyte b;jchar c;jshort s;jint i;jlong j;jfloat f;jdouble d;jobject l;
} jvalue;
3.5 类型签名
JNI 使用 Java VM 的类型签名表示法。下表列出了这些类型签名:
例如,Java 方法:
long f (int n, String s, int[] arr);
的类型特征,如下:
(ILjava/lang/String;[I)J
String的全称类文件位于:libcore/ojluni/src/main/java/java/lang/String.java
package java.lang;
3.6 修改后的 UTF-8 字符串
JNI 使用修改后的 UTF-8 字符串来表示各种字符串类型。修改后的 UTF-8 字符串与 Java VM 使用的字符串相同。修改后的 UTF-8 字符串经过编码后,只包含非空 ASCII 字符的字符序列,可使用每个字符一个字节来表示,但所有 Unicode 字符均可表示。
\u0001 到 \u007F 范围内的所有字符都用一个字节表示,如下所示:
0xxxxxxx
字节中的七位数据给出了所代表字符的值。
空字符 ( '\u0000' ) 和范围在 '\u0080' 到 '\u07FF' 之间的字符由一对字节 x 和 y 表示:
x: 110xxxxx x: 110xxxxx
y: 10yyyyyy y: 10yyyyyy
字节表示值为 ((x & 0x1f ) << 6 ) + (y & 0x3f ) 的字符。
'\u0800' 至 '\uFFFF' 范围内的字符由 3 个字节 x、y 和 z 表示:
x: 1110xxxx x: 1110xxxx
y: 10yyyyyy y: 10yyyyyy
z: 10zzzzzz z: 10zzzzzz
值为 ((x & 0xf ) << 12 ) + ((y & 0x3f ) << 6 ) + (z & 0x3f ) 的字符用字节表示。
码位在 U+FFFF 以上的字符(即所谓的补充字符)通过对其 UTF-16 表示形式的两个代理码单元进行单独编码来表示。每个代理编码单元由三个字节表示。也就是说,补充字符由 u、v、w、x、y 和 z 六个字节表示:
u: 11101101 u: 11101101
v: 1010vvvv v: 1010vvvv
w: 10wwwwww w: 10wwwwww
x: 11101101 x: 11101101
y: 1011yyyy y: 1011yyyy
z: 10zzzzzz z: 10zzzzzz
数值为 0x10000+((v&0x0f)<<16)+((w&0x3f)<<10)+(y&0x0f)<<6)+(z&0x3f) 的字符由这六个字节表示。
多字节字符的字节在 class 文件中按大字节(高字节在前)顺序存储。
这种格式与标准 UTF-8 格式有两点不同。首先,空字符 (char)0 使用双字节格式编码,而不是单字节格式。这意味着修改后的 UTF-8 字符串永远不会嵌入空字符。其次,只使用标准 UTF-8 的一字节、二字节和三字节格式。Java 虚拟机不识别标准 UTF-8 的四字节格式,而是使用自己的两倍三字节格式。
有关标准 UTF-8 格式的更多信息,请参见《Unicode Encoding Forms of The Unicode Standard》4.0 版第 3.9 节。
下一篇: