app。changeObject(anObj);
System。out。println(〃Java: 〃 + anObj。aValue);
}
private native void
changeObject(MyJavaClass obj);
static {
System。loadLibrary(〃UseObjImpl〃);
}
}
编译好代码,并将。class 文件传递给 javah 后,就可以实现固有方法。在下面这个例子中,一旦取得字段和
方法 ID,就会通过 JNI 函数访问它们。
JNIEXPORT void JNICALL
653
…………………………………………………………Page 655……………………………………………………………
Java_UseObjects_changeObject(
JNIEnv * env; jobject jThis; jobject obj) {
jclass cls;
jfieldID fid;
jmethodID mid;
int value;
cls = env…》GetObjectClass(obj);
fid = env…》GetFieldID(cls;
〃aValue〃; 〃I〃);
mid = env…》GetMethodID(cls;
〃divByTwo〃; 〃()V〃);
value = env…》GetIntField(obj; fid);
printf(〃Native: %dn〃; value);
env…》SetIntField(obj; fid; 6);
env…》CallVoidMethod(obj; mid);
value = env…》GetIntField(obj; fid);
printf(〃Native: %dn〃; value);
}
除第一个自变量外,C++函数会接收一个 jobject,它代表Java 对象引用“固有”的那一面——那个引用是
我们从 Java 代码里传递的。我们简单地读取 aValue,把它打印出来,改变这个值,调用对象的divByTwo()
方法,再将值重新打印一遍。
为访问一个字段或方法,首先必须获取它的标识符。利用适当的JNI 函数,可方便地取得类对象、元素名以
及签名信息。这些函数会返回一个标识符,利用它可访问对应的元素。尽管这一方式显得有些曲折,但我们
的固有方法确实对Java 对象的内部布局一无所知。因此,它必须通过由 JVM 返回的索引访问字段和方法。这
样一来,不同的JVM 就可实现不同的内部对象布局,同时不会对固有方法造成影响。
若运行 Java 程序,就会发现从 Java 那一侧传来的对象是由我们的固有方法处理的。但传递的到底是什么
呢?是指针,还是Java 引用?而且垃圾收集器在固有方法调用期间又在做什么呢?
垃圾收集器会在固有方法执行期间持续运行,但在一次固有方法调用期间,我们的对象可保证不会被当作
“垃圾”收集去。为确保这一点,事先创建了“局部引用”,并在固有方法调用之后立即清除。由于它们的
“生命期”与调用过程息息相关,所以能够保证对象在固有方法调用期间的有效性。
由于这些引用会在每次函数调用的时候创建和破坏,所以不可在static 变量中制作固有方法的局部副本(本
地拷贝)。若希望一个引用在函数存在期间持续有效,就需要一个全局引用。全局引用不是由JVM 创建的,
但通过调用特定的 JNI 函数,程序员可将局部引用扩展为全局引用。创建一个全局引用时,需对引用对象的
“生存时间”负责。全局引用(以及它引用的对象)会一直留在内存里,直到用特定的JNI 函数明确释放了
这个引用。它类似于C 的malloc()和 free()。
A。1。4 JNI 和 Java 异常
利用 JNI,可丢弃、捕捉、打印以及重新丢弃Java 异常,就象在一个 Java 程序里那样。但对程序员来说,
需自行调用专用的JNI 函数,以便对异常进行处理。下面列出用于异常处理的一些JNI 函数:
■Throw():丢弃一个现有的异常对象;在固有方法中用于重新丢弃一个异常。
■ThrowNew():生成一个新的异常对象,并将其丢弃。
■ExceptionOccurred():判断一个异常是否已被丢弃,但尚未清除。
■ExceptionDescribe():打印一个异常和堆栈跟踪信息。
■ExceptionClear():清除一个待决的异常。
■FatalError():造成一个严重错误,不返回。
在所有这些函数中,最不能忽视的就是ExceptionOccurred()和ExceptionClear()。大多数JNI 函数都能产
生异常,而且没有象在 Java 的try 块内的那种语言特性可供利用。所以在每一次 JNI 函数调用之后,都必须
调用ExceptionOccurred(),了解异常是否已被丢弃。若侦测到一个异常,可选择对其加以控制(可能时还
要重新丢弃它)。然而,必须确保异常最终被清除。这可以在自己的函数中用ExceptionClear()来实现;若
异常被重新丢弃,也可能在其他某些函数中进行。但无论如何,这一工作是必不可少的。
654
…………………………………………………………Page 656……………………………………………………………
我们必须保证异常被彻底清除。否则,假若在一个异常待决的情况下调用一个JNI 函数,获得的结果往往是
无法预知的。也有少数几个JNI 函数可在异常时安全调用;当然,它们都是专门的异常控制函数。
A。1。5 JNI 和线程处理
由于Java 是一种多线程语言,几个线程可能同时发出对一个固有方法的调用(若另一个线程发出调用,固有
方法可能在运行期间暂停)。此时,完全要由程序员来保证固有调用在多线程的环境中安全进行。例如,要
防范用一种未进行监视的方法修改共享数据。此时,我们主要有两个选择:将固有方法声明为“同步”,或
在固有方法内部采取其他某些策略,确保数据处理正确地并发进行。
此外,绝对不要通过线程传递 JNIEnv,因为它指向的内部结构是在“每线程”的基础上分配的,而且包含了
只对那些特定的线程才有意义的信息。
A。1。6 使用现成代码
为实现JNI 固有方法,最简单的方法就是在一个Java 类里编写固有方法的原型,编译那个类,再通过 javah
运行。class 文件。但假若我们已有一个大型的、早已存在的代码库,而且想从Java 里调用它们,此时又该
如何是好呢?不可将DLL 中的所有函数更名,使其符合 JNI 命名规则,这种方案是不可行的。最好的方法是
在原来的代码库“外面”写一个封装DLL。Java 代码会调用新 DLL 里的函数,后者再调用原始的DLL 函数。
这个方法并非仅仅是一种解决方案;大多数情况下,我们甚至必须这样做,因为必须面向对象引用调用 JNI
函数,否则无法使用它们。
A。2 微软的解决方案
到本书完稿时为止,微软仍未提供对JNI 的支持,只是用自己的专利方法提供了对非Java 代码调用的支持。
这一支持内建到编译器 Microsoft JVM 以及外部工具中。只有程序用 Microsoft Java 编译器编译,而且只有
在Microsoft Java 虚拟机(JVM)上运行的时候,本节讲述的特性才会有效。若计划在因特网上发行自己的
应用,或者本单位的内联网建立在不同平台的基础上,就可能成为一个严重的问题。
微软与Win32 代码的接口为我们提供了连接 Win32 的三种途径:
(1) J/Direct:方便调用Win32 DLL 函数的一种途径,具有某些限制。
(2) 本原接口(RNI):可调用Win32 DLL 函数,但必须自行解决“垃圾收集”问题。
(3) Java/ 集成:可从 Java 里直接揭示或调用 服务。
后续的小节将分别探讨这三种技术。
写作本书的时候,这些特性均通过了Microsoft SDK for Java 2。0 beta 2 的支持。可从微软公司的Web 站
点下载这个开发平台(要经历一个痛苦的选择过程,他们叫作“Active Setup”)。Java SDK 是一套命令行
工具的集合,但编译引擎可轻易嵌入Developer Studio 环境,以便我们用 Visual J++ 1。1 来编译 Java 1。1
代码。
A。3 J/Direct
J/Direct 是调?
小说推荐
- 软件工程实践者的思想(PDF格式)
- -Page 1-大 道 至 简—软件工程实践者的思想周爱民(Aimingoo 著-Page 2-序2004 年 11 月初爱民(Aimingoo)第一次把他的书稿给我,我翻看了一下,第一反应讲的是感想。这不错,在技
- 最新章:第26章
- 深入浅出MFC第2版(PDF格式)
- -Page 1-Page 2-山高月小山高月小 水落石出水落石出山高月小山高月小 水落石出水落石出-Page 3-深入淺出MFC(第版 使用Visual C 5.0 MFC 4.2)Dissecting MFC(Second Edition Using Visual C 5.0 MFC 4.2)侯俊
- 最新章:第309章
- VB2008从入门到精通(PDF格式英文版)
- -Page 1(R)The eXperT’s Voice inBeginningVB 2008From Novice to ProfessionalChristian Gross-Page 2-Page 3-Beginning VB 2008From Novice to Professional■C
- 最新章:第214章
- C语言游戏编程从入门到精通(PDF格式)
- -Page 1-Page 2-Page 3-Page 4-Page 5-Page 6-Page 7-Page 8-Page 9-Page 10-Page 11-Page 12-Page 13-Page 14
- 最新章:第4章
- JMS简明教程(PDF格式)
- -Page 1-JMS1.1规范中文版卫建军2007‐11‐22-Page 2
- 最新章:第28章
- C语言实例教程(PDF格式)
- -Page 1-前 言Visual C+是开发运行于Windows 95和Windows NT环境下的Win32应用程序的可视化编程工具中最重要的成员之一,它为软件开发人员提供了完整的编辑、编译和调试工具和建立于Win32 API(ApplicationProgramming Interface)基
- 最新章:第143章
- 神祗之眼 (正式版)第7卷(全文完)作者:百里芜虚
- 第五十一章离12月25日的圣诞节还有两天,纽约已经换上了节日的盛装,几天前的一场大雪令整个城市一片银白。人们笑逐颜开,都纷纷开始为节日做准备,商家为了在节日打开销路纷纷推出各种优惠促销手段,纽约的大街小巷全都这样热闹。依沙那被老婆打发出来买过节要用的杂货,而女儿则和凯妮一起到百货商场去买衣服去了。对
- 最新章:第23章
- SQL语言艺术(PDF格式)
- -Page 1-SQLSSQQLL语言艺术内容介绍本书分为12章,每一章包含许多原则或准则,并通过举例的方式对原则进行解释说明。这些例子大多来自于实际案例,对九种SQL经典查询场景以及其性能影响讨论,非常便于实践,为你数据库应用维护人员阅读。资深 SQL 专家 Stéphane Faroult倾力打
- 最新章:第27章
- php程序设计简明教程(DOC格式)
- -Page 1-PHP 程序设计简明教程PHP 讲义 第 1 页 共 90 页-Page 2-目录序 4第一章 PHP 简介 6
- 最新章:第31章