【JNI编程】JNI类型和数据结构

172 阅读3分钟

本节主要讨论JNI如何将Java类型映射到本地C类型。

一、原始类型

下表描述了Java基本类型及其依赖于机器的本地对等类型。

Java类型本地类型描述
booleanjbooleanunsigned 8 bits
bytejbytesigned 8 bits
charjcharunsigned 16 bits
shortjshortsigned 16 bits
intjintsigned 32 bits
longjlongsigned 64 bits
floatjfloat32 bits
doublejdouble64 bits
voidvoidN/A

为了方便起见,提供了以下定义。

#define JNI_FALSE  0 
#define JNI_TRUE   1 

jsize 整数类型用于描述基本索引和大小:

typedef jint jsize; 

二、引用类型

JNI包含许多与不同类型的Java对象对应的引用类型。JNI引用类型组织在下图所示的层次结构中。

Reference Type Hierarchy

在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类型
Zboolean
Bbyte
Cchar
Sshort
Iint
Jlong
Ffloat
Ddouble
L fully-qualified-class ;fully-qualified-class
[ typetype[]
( arg-types ) ret-typemethod 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中的所有字符都由单个字节表示,如下所示:
jni-utf8-1
字节中的7位数据给出所表示的字符的值。

空字符(’\u0000’)和’\u0080’到’\u07FF’范围内的字符由一对字节x和y表示:
jni-utf8-2
字节用值((x & 0x1f) << 6) + (y & 0x3f)表示字符。

‘\u0800’到’\uFFFF’范围内的字符由3个字节x,y和z表示:
jni-utf8-3
具有值((x & 0xf) << 12) + ((y & 0x3f) << 6) + (z & 0x3f)的字符由以上字节表示。

代码点高于U+FFFF的字符(所谓的补充字符)通过分别编码其UTF-16表示的两个代理代码单元来表示。每个代理代码单元由三个字节表示。这意味着,补充字符由六个字节u,v,w,x,y和z表示:
jni-utf8-4
值为0x10000+((v&0x0f)<<16)+((w&0x3f)<<10)+(y&0x0f)<<6)+(z&0x3f)的字符由六个字节表示。

多字节字符的字节按大端顺序存储在类文件中。

此格式与标准UTF-8格式有两点不同。

首先,使用双字节格式而不是单字节格式对空字符(char)0进行编码。这意味着修改后的UTF-8字符串永远不会嵌入空值。

其次,仅使用标准UTF-8的单字节,双字节和三字节格式。

JVM无法识别标准UTF-8的四字节格式;它使用自己的两倍三字节格式代替。