The quiter you become,the more you are able to hear!

JNI官方文档-Chapter 3:JNI Types and Data Structures

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。