第三章:JNI类型和数据结构
本章讨论了JNI如何将Java类型映射到本机C类型。
本章涵盖以下主题:
基本类型
以下表格描述了Java基本类型及其与机器相关的本机等效类型。
Java类型 | 本机类型 | 描述 |
---|---|---|
boolean | jboolean | 无符号8位 |
byte | jbyte | 有符号8位 |
char | jchar | 无符号16位 |
short | jshort | 有符号16位 |
int | jint | 有符号32位 |
long | jlong | 有符号64位 |
float | jfloat | 32位 |
double | jdouble | 64位 |
void | void | 不适用 |
以下定义供参考。
#define JNI_FALSE 0
#define JNI_TRUE 1
jsize
整数类型用于描述基数索引和大小:
typedef jint jsize;
引用类型
JNI包括一些引用类型,对应不同类型的Java对象。JNI引用类型组织如下层次结构:
jobject
jclass
(java.lang.Class
对象)jstring
(java.lang.String
对象)jarray
(数组)jobjectArray
(对象数组)jbooleanArray
(boolean
数组)jbyteArray
(byte
数组)jcharArray
(char
数组)jshortArray
(short
数组)jintArray
(int
数组)jlongArray
(long
数组)jfloatArray
(float
数组)jdoubleArray
(double
数组)
jthrowable
(java.lang.Throwable
对象)
在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; /* 不透明结构 */
typedef struct _jfieldID *jfieldID; /* 字段ID */
struct _jmethodID; /* 不透明结构 */
typedef struct _jmethodID *jmethodID; /* 方法ID */
值类型
jvalue
联合类型用作参数数组中的元素类型。它声明如下:
typedef union jvalue {
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
} jvalue;
类型签名
JNI使用Java虚拟机的类型签名表示。以下表格显示了这些类型签名。
类型签名 | Java类型 |
---|---|
Z |
boolean |
B |
byte |
C |
char |
S |
short |
I |
int |
J |
long |
F |
float |
D |
double |
L 完全限定类 ; |
完全限定类 |
[ 类型 |
类型[] |
( 参数类型 ) 返回类型 |
方法类型 |
例如,Java方法:
long f (int n, String s, int[] arr);
具有以下类型签名:
(ILjava/lang/String;[I)J
修改后的UTF-8字符串
JNI使用修改后的UTF-8字符串来表示各种字符串类型。修改后的UTF-8字符串与Java虚拟机使用的相同。修改后的UTF-8字符串被编码,以便仅包含仅包含非空ASCII字符的字符序列可以使用每个字符仅一个字节表示,但所有Unicode字符都可以表示。
范围在\u0001到\u007F之间的所有字符由单个字节表示,如下:
0xxxxxxx
字节中的七位数据给出了所表示字符的值。
空字符('\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
)的字符由这些字节表示。
代码点在U+FFFF以上的字符(所谓的补充字符)通过分别编码其UTF-16表示的两个代理代码单元来表示。每个代理代码单元由三个字节表示。这意味着,补充字符由六个字节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)的字符由这六个字节表示。
多字节字符的字节以大端(高字节在前)顺序存储在class
文件中。
此格式与标准UTF-8格式之间存在两个差异。首先,空字符(char)0
使用两字节格式而不是一个字节格式进行编码。这意味着修改后的UTF-8字符串永远不会有嵌入的空字符。其次,仅使用标准UTF-8的一个字节、两字节和三字节格式。Java虚拟机不识别标准UTF-8的四字节格式;它使用自己的两次三字节格式代替。
有关标准UTF-8格式的更多信息,请参阅The Unicode Standard, Version 4.0的3.9 Unicode编码形式部分。