Author: geneblue
Blog: https://geneblue.github.io/
本章讲述JNI是如何映射java类型到native C类型的。
Primitive Types
表3-1表明了java基本类型和平台依赖的(machine-dependent)等价native类型。
表3-1:基本类型和等价native类型Java类型 | Native类型 | 描述 |
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;
Reference Types
JNI中也包含了大量的引用类型,这些引用类型是针对不同的java对象的。JNI引用类型以分层形式进行组织,如图所示:
在C中,所有的JNI引用类型都被看做jobject类型,如:
typedef jobject jclass;
在C++中,JNI引入了一组虚拟类来强制子类型关系(the subtyping relationship),如:
class _jobject {};
class _jclass : public _jobject {};
...
typedef _jobject *jobject;
typedef _jclass *jclass;
Field and Method IDs
方法和字段ID符合C的指针类型:
struct _jfieldID; /* opaque structure */
typedef struct _jfieldID *jfieldID; /* field IDs */
struct _jmethodID; /* opaque structure */
typedef struct _jmethodID *jmethodID; /* method IDs */
The Value Type
jvalue联合类型在参数数组中常被用于元素类型,定义如下:
typedef union jvalue {
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
} jvalue;
Type Signatures
JNI使用JVM的类型签名。表3-2表述了这些类型签名:
表3-2:JVM类型签名
签名类型 | Java类型 |
Z | boolean |
B | byte |
C | char |
S | short |
I | int |
J | long |
F | float |
D | double |
Lfully-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
Modified UTF-8 Strings
JNI使用一种修改版的UTF-8字符编码来表示各种字符串类型。Modified UTF-8字符串与JVM中使用的是相似的。
Modified UTF-8字符串编码的目的在于,使那些只包含非空ASCII字符的字符序列每个字符用一个字节表示,但不是所有的Unicode字符都可以表示。
所有在范围'001'和'07F'的字符都以一个字节表示,如下:
在该字节中,有7个bit用于表示字符串的值。
空字符('000')和'080'与'7FF'范围内的字符用两个字节X和Y表示:
字节表示的字符的值为:((X&0x1f)<<6)+(Y&0x3f)
范围在'800'到''的字符用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)
多字节字符以大端方式存储在class文件中。
Modified UTF-8编码格式和标准的UTF-8编码格式存在两点不同。首先,空字符(char) 0 是以两个字节编码的而不是一个字节。这意味着Modified UTF-8字符串不会嵌入 null。其次,只有一字节,两字节和三字节的标准UTF-8编码格式被使用。JVM不会识别四字节的标准UTF-8格式字符,而是使用自有的two-times-three-byte格式替代。
更多标准UTF-8编码方面的信息最好参见section 3.9 Unicode Encoding Forms of The Unicode Standard, Version 4.0。