本文将讨论JNI是如何将Java类型映射到native C类型的。
基本类型
下表展示了Java基本类型以及与它们对等的native类型:
Java类型 | native类型 | 描述 |
---|---|---|
boolean | jboolean | 无符号(unsigned)8bits |
byte | jbyte | 有符号(signed)8bits |
char | jchar | unsigned 16bits |
short | jshort | signed 16bits |
int | jint | signed 32bits |
long | jlong | signed 64bits |
float | jfloat | 32bits |
double | jdouble | 64bits |
void | void | - |
以下定义是为了提供方便:
#define JNI_FALSE 0 #define JNI_TRUE 1
jsize
整数类型用来描述基数指数和大小:typedef jint jsize;
引用类型
JNI包含许多不同种类的Java对象对应不同的引用类型,JNI引用类型的层级结构如下:
jobject
jclass
(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;
字段和方法id
字段和方法id是常规的C指针类型:
struct _jfieldID; /* opaque structure */ typedef struct _jfieldID *jfieldID; /* field IDs */ struct _jmethodID; /* opaque structure */ typedef struct _jmethodID *jmethodID; /* method IDs */
值类型
联合体jvalue
用作参数数组的元素类型,定义如下:
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类型 | native类型 | 描述 |
---|---|---|
boolean | jboolean | 无符号(unsigned)8bits |
byte | jbyte | 有符号(signed)8bits |
char | jchar | unsigned 16bits |
short | jshort | signed 16bits |
int | jint | signed 32bits |
long | jlong | signed 64bits |
float | jfloat | 32bits |
double | jdouble | 64bits |
void | void | - |
例如Java方法
long f (int n, String s, int[] arr);
它的类型签名如下
(ILjava/lang/String;[I)J
Modified UTF-8(MUTF-8)字符串
JNI使用modified UTF-8字符串表示各种字符串类型。Modified UTF-8字符串也是JVM中使用的。Modified UTF-8 经过编码,每个字符仅使用一个字节就能表示仅包含非空ASCII字符的字符序列,但所有的Unicode字符都能被表示。
从\u0001
到\u007
区间内的所有的字符被单一字节表示,如
- 0xxxxxxx
这个字节中的7位数据是字符表示的值
空字符(’\u0000
‘)和 从'\u0080'
到 '\u07FF'
区间中的字符用一对字节x和y表示:
- x:
110xxxxx
- y:
10yyyyyy
这些字节代表值为 ((x & 0x1f
) << 6
) + (y & 0x3f
)的字符串。
从'\u0800'
到'\uFFFF'
范围的字符由3个字节x,y和z表示:
- x:
1110xxxx
- y:
10yyyyyy
- z:
10zzzzzz
这些字节代表值为 ((x & 0xf
) << 12
) + ((y & 0x3f
) << 6
) + (z & 0x3f
) 的字符串。
码位(code point)在U+FFFF之上(所谓的补充字符)的字符分别由两个UTF-16表示的替代码单元表示。每个替代码单元由3个字节表示,这就意味着补充字符由6个字节表示,u, v, w, x, y, 及 z:
- u:
11101101
- v:
1010vvvv
- w:
10wwwwww
- x:
11101101
- y:
1011yyyy
- z:
10zzzzzz
值为0x10000+((v&0x0f)<<16)+((w&0x3f)<<10)+(y&0x0f)<<6)+(z&0x3f)的字符由6字节表示。
多字节字符的字节在class中以大端序(big-endian)的方式存储。
MUTF-8和标准的UTF-8由两个区别。首先,空字符(char)0使用二字节格式编码,而不是一字节。这就意味着MUTF-8字符串不嵌入空字符。其次,只有一字节、二字节和三字节格式的标准UTF-8被使用。JVM不承认四字节的标准UTF-8字符,它使用自己的两倍三字节(two-times-three-byte)格式代替。
获取更多关于标准UTF-8的信息,查阅 Ecoding Forms of The Unicode Standard, Version 4.0