本节主要讨论JNI如何将Java类型映射到本地C类型。
一、原始类型
下表描述了Java基本类型及其依赖于机器的本地对等类型。
Java类型 | 本地类型 | 描述 |
---|---|---|
boolean | jboolean | unsigned 8 bits |
byte | jbyte | signed 8 bits |
char | jchar | unsigned 16 bits |
short | jshort | signed 16 bits |
int | jint | signed 32 bits |
long | jlong | signed 64 bits |
float | jfloat | 32 bits |
double | jdouble | 64 bits |
void | void | N/A |
为了方便起见,提供了以下定义。
#define JNI_FALSE 0
#define JNI_TRUE 1
jsize 整数类型用于描述基本索引和大小:
typedef jint jsize;
二、引用类型
JNI包含许多与不同类型的Java对象对应的引用类型。JNI引用类型组织在下图所示的层次结构中。
在C语言中,所有其他JNI引用类型都被定义为与jobject相同。例如:
typedef jobject jclass;
在C++中,JNI引入了一组虚拟类来加强子类型关系。例如:
class _jobject {};
class _jclass : public _jobject {};
...
typedef _jobject *jobject;
typedef _jclass *jclass;
三、 字段和方法ID
方法和字段ID是常规的C指针类型:
struct _jfieldID; /* opaque structure */
typedef struct _jfieldID *jfieldID; /* field IDs */
struct _jmethodID; /* opaque structure */
typedef struct _jmethodID *jmethodID; /* method IDs */
四、 值类型
jvalue union类型用作参数数组中的元素类型。声明如下:
typedef union jvalue {
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
} jvalue;
五、 类型签名
JNI使用JVM的类型签名表示。下表显示了这些类型签名。
类型签名 | Java类型 |
---|---|
Z | boolean |
B | byte |
C | char |
S | short |
I | int |
J | long |
F | float |
D | double |
L fully-qualified-class ; | fully-qualified-class |
[ type | type[] |
( arg-types ) ret-type | method type |
例如,Java方法:
long f (int n, String s, int[] arr);
具有以下类型签名:
(ILjava/lang/String;[I)J
六、修改UTF-8编码的字符串
JNI使用修改后的UTF-8字符串来表示各种字符串类型。修改后的UTF-8字符串与JVM使用的字符串相同。对修改后的UTF-8字符串进行编码,以便只包含非空ASCII字符的字符序列只能用每个字符一个字节表示,但是可以表示所有Unicode字符。
范围\u0001到\u007F中的所有字符都由单个字节表示,如下所示:
字节中的7位数据给出所表示的字符的值。
空字符(’\u0000’)和’\u0080’到’\u07FF’范围内的字符由一对字节x和y表示:
字节用值((x & 0x1f) << 6) + (y & 0x3f)表示字符。
‘\u0800’到’\uFFFF’范围内的字符由3个字节x,y和z表示:
具有值((x & 0xf) << 12) + ((y & 0x3f) << 6) + (z & 0x3f)的字符由以上字节表示。
代码点高于U+FFFF的字符(所谓的补充字符)通过分别编码其UTF-16表示的两个代理代码单元来表示。每个代理代码单元由三个字节表示。这意味着,补充字符由六个字节u,v,w,x,y和z表示:
值为0x10000+((v&0x0f)<<16)+((w&0x3f)<<10)+(y&0x0f)<<6)+(z&0x3f)的字符由六个字节表示。
多字节字符的字节按大端顺序存储在类文件中。
此格式与标准UTF-8格式有两点不同。
首先,使用双字节格式而不是单字节格式对空字符(char)0进行编码。这意味着修改后的UTF-8字符串永远不会嵌入空值。
其次,仅使用标准UTF-8的单字节,双字节和三字节格式。
JVM无法识别标准UTF-8的四字节格式;它使用自己的两倍三字节格式代替。