03-JNI 类型和数据结构

上一篇: 02-设计概述


本章讨论 JNI 如何将 Java 类型映射为本地 C 类型。

3.1 原始类型

下表描述了 Java 原始类型及其与机器相关的本地等价类型。

为方便起见,定义如下:

cpp 复制代码
#define JNI_FALSE  0
#define JNI_TRUE   1

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

cpp 复制代码
typedef jint jsize;

3.2 引用类型

JNI 包括许多与Java 对象相对应的、不同类型的引用类型。JNI 引用类型按以下层次结构组织:

cpp 复制代码
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 相同++。例如:

cpp 复制代码
typedef jobject jclass;

在 C++ 中,JNI 引入了一组假类来执行子类型关系。例如:

cpp 复制代码
class _jobject {};
class _jclass : public _jobject {};
// ...
typedef _jobject *jobject;
typedef _jclass *jclass;

3.3 字段和方法 ID

++方法和字段 ID 是常规的 C 指针类型++:

cpp 复制代码
struct _jfieldID;              /* opaque structure */
typedef struct _jfieldID *jfieldID;   /* field IDs */

struct _jmethodID;              /* opaque structure */
typedef struct _jmethodID *jmethodID; /* method IDs */

3.4 值类型

jvalue 联合类型在参数数组中用作元素类型。其声明如下:

cpp 复制代码
typedef union jvalue {
    jboolean z;
    jbyte    b;
    jchar    c;
    jshort   s;
    jint     i;
    jlong    j;
    jfloat   f;
    jdouble  d;
    jobject  l;
} jvalue;

3.5 类型签名

JNI 使用 Java VM 的类型签名表示法。下表列出了这些类型签名:

例如,Java 方法:

java 复制代码
long f (int n, String s, int[] arr);

的++类型特征++,如下:

cpp 复制代码
(ILjava/lang/String;[I)J

String的全称类文件位于:libcore/ojluni/src/main/java/java/lang/String.java

++package java.lang;++

3.6 修改后的 UTF-8 字符串

JNI 使用修改后的 UTF-8 字符串来表示各种字符串类型。++修改后的 UTF-8 字符串与 Java VM 使用的字符串相同++ 。修改后的 UTF-8 字符串经过编码后,只包含非空 ASCII 字符的字符序列,可使用++每个字符一个字节++来表示,但所有 Unicode 字符均可表示。

\u0001 到 \u007F 范围内的所有字符都用一个字节表示,如下所示:

bash 复制代码
0xxxxxxx

字节中的七位数据给出了所代表字符的值。

空字符 ( '\u0000' ) 和范围在 '\u0080' 到 '\u07FF' 之间的字符由一对字节 x 和 y 表示:

bash 复制代码
x: 110xxxxx x: 110xxxxx
y: 10yyyyyy y: 10yyyyyy

字节表示值为 ((x & 0x1f ) << 6 ) + (y & 0x3f ) 的字符。

'\u0800' 至 '\uFFFF' 范围内的字符由 3 个字节 x、y 和 z 表示:

bash 复制代码
x: 1110xxxx x: 1110xxxx
y: 10yyyyyy y: 10yyyyyy
z: 10zzzzzz z: 10zzzzzz

值为 ((x & 0xf ) << 12 ) + ((y & 0x3f ) << 6 ) + (z & 0x3f ) 的字符用字节表示。

码位在 U+FFFF 以上的字符(即所谓的补充字符)通过对其 UTF-16 表示形式的两个代理码单元进行单独编码来表示。每个代理编码单元由三个字节表示。也就是说,补充字符由 u、v、w、x、y 和 z 六个字节表示:

bash 复制代码
u: 11101101 u: 11101101
v: 1010vvvv v: 1010vvvv
w: 10wwwwww w: 10wwwwww
x: 11101101 x: 11101101
y: 1011yyyy y: 1011yyyy
z: 10zzzzzz 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 格式的更多信息,请参见《Unicode Encoding Forms of The Unicode Standard》4.0 版第 3.9 节。


下一篇:04-JNI函数​​​​​​​

相关推荐
常利兵6 分钟前
2026年,Android开发已死?不,它正迎来黄金时代!
android
wangjialelele8 分钟前
Linux中的进程管理
java·linux·服务器·c语言·c++·个人开发
历程里程碑10 分钟前
普通数组----轮转数组
java·数据结构·c++·算法·spring·leetcode·eclipse
李日灐14 分钟前
C++进阶必备:红黑树从 0 到 1: 手撕底层,带你搞懂平衡二叉树的平衡逻辑与黑高检验
开发语言·数据结构·c++·后端·面试·红黑树·自平衡二叉搜索树
晔子yy19 分钟前
如何设计让你的程序同时处理10w条数据
java
汉克老师20 分钟前
GESP2025年6月认证C++二级( 第一部分选择题(1-8))
c++·循环结构·表达式·分支结构·gesp二级·gesp2级
Risehuxyc23 分钟前
备份三个PHP程序
android·开发语言·php
rainbow688925 分钟前
C++高性能框架Drogon:后端开发新标杆
c++
Yvonne爱编码26 分钟前
链表高频 6 题精讲 | 从入门到熟练掌握链表操作
java·数据结构·链表
Q741_14727 分钟前
C++ 优先级队列 大小堆 模拟 力扣 703. 数据流中的第 K 大元素 每日一题
c++·算法·leetcode·优先级队列·