- 写在前面的话
- 引言
- 第 1 章 对象入门
- 第 2 章 一切都是对象
- 第 3 章 控制程序流程
- 第 4 章 初始化和清除
- 第 5 章 隐藏实施过程
- 第 6 章 类再生
- 第 7 章 多形性
- 第 8 章 对象的容纳
- 第 9 章 违例差错控制
- 第 10 章 Java IO 系统
- 第 11 章 运行期类型鉴定
- 第 12 章 传递和返回对象
- 第 十三 章 创建窗口和程序片
- 第 14 章 多线程
- 第 15 章 网络编程
- 第 16 章 设计范式
- 第 17 章 项目
- 附录 A 使用非 JAVA 代码
- 附录 B 对比 C++和 Java
- 附录 C Java 编程规则
- 附录 D 性能
- 附录 E 关于垃圾收集的一些话
- 附录 F 推荐读物
A.1.2 访问 JNI 函数:JNIEnv 自变量
利用 JNI 函数,程序员可从一个固有方法的内部与 JVM 打交道。正如大家在前面的例子中看到的那样,每个 JNI 固有方法都会接收一个特殊的自变量作为自己的第一个参数:JNIEnv 自变量——它是指向类型为 JNIEnv_的一个特殊 JNI 数据结构的指针。JNI 数据结构的一个元素是指向由 JVM 生成的一个数组的指针;该数组的每个元素都是指向一个 JNI 函数的指针。可从固有方法的内部发出对 JNI 函数的调用,做法是撤消对这些指针的引用(具体的操作实际很简单)。每种 JVM 都以自己的方式实现了 JNI 函数,但它们的地址肯定位于预先定义好的偏移处。
利用 JNIEnv 自变量,程序员可访问一系列函数。这些函数可划分为下述类别:
- 获取版本信息
- 进行类和对象操作
- 控制对 Java 对象的全局和局部引用
- 访问实例字段和静态字段
- 调用实例方法和静态方法
- 执行字串和数组操作
- 产生和控制 Java 异常
JNI 函数的数量相当多,这里不再详述。相反,我会向大家揭示使用这些函数时背后的一些基本原理。欲了解更详细的情况,请参阅自己所用编译器的 JNI 文档。
若观察一下 jni.h 头文件,就会发现在#ifdef _cplusplus 预处理器条件的内部,当由 C++编译器编译时,JNIEnv_结构被定义成一个类。这个类包含了大量内嵌函数。通过一种简单而且熟悉的语法,这些函数让我们可以从容访问 JNI 函数。例如,前例包含了下面这行代码:
(*jEnv)->ReleaseStringUTFChars(jEnv, jMsg,msg);
它在 C++里可改写成下面这个样子:
jEnv->ReleaseStringUTFChars(jMsg,msg);
大家可注意到自己不再需要同时撤消对 jEnv 的两个引用,相同的指针不再作为第一个参数传递给 JNI 函数调用。在这些例子剩下的地方,我会使用 C++风格的代码。
1. 访问 Java 字串
作为访问 JNI 函数的一个例子,请思考上述的代码。在这里,我们利用 JNIEnv 的自变量 jEnv 来访问一个 Java 字串。Java 字串采取的是 Unicode 格式,所以假若收到这样一个字串,并想把它传给一个非 Unicode 函数(如 printf()),首先必须用 JNI 函数 GetStringUTFChars() 将其转换成 ASCII 字符。该函数能接收一个 Java 字串,然后把它转换成 UTF-8 字符(用 8 位宽度容纳 ASCII 值,或用 16 位宽度容纳 Unicode;若原始字串的内容完全由 ASCII 构成,那么结果字串也是 ASCII)。
GetStringUTFChars 是 JNIEnv 间接指向的那个结构里的一个字段,而这个字段又是指向一个函数的指针。为访问 JNI 函数,我们用传统的 C 语法来调用一个函数(通过指针)。利用上述形式可实现对所有 JNI 函数的访问。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论