首页 » Android程序设计:第2版 » Android程序设计:第2版全文在线阅读

《Android程序设计:第2版》本地方法和JNI调用

关灯直达底部

JNI制定了一些规范,支持其他语言调用它的方法。本地方法的变化(实质上是C或C++库)大于Java代码的变化。

本地方法调用规范

当虚拟机(VM)(在Android中,即Dalvik)调用C或C++实现的函数时,它会传递两个特殊的参数:

·JNIEnv指针,指向虚拟机中调用本地方法的线程。

·Jobject指针,是调用类的引用。

这些参数会被“透明”地传递给Java代码,也就是说,它们不会出现在声明调用Java代码的方法签名中。Java调用只是显式传递所调用的函数需要的其他任何参数。

JNI方法调用可能看起来如下:


/* sample method where the Java call passed no parameters */void Java_ClassName_MethodName (JNIEnv *env, jobject obj) {    /* do something */}/* another sample method with two parameters passed, returning a double */jdouble Java_ClassName_MethodName ( JNIEnv* env, jobject obj,                                                        jdouble x, jdouble y) {    return x + y;}  

这些示例显示了自动传递给每个本地方法的两个参数,以及匹配Java类型的两个参数。

当本地方法被调用时,它和调用它的Java代码在相同的进程和线程中运行。正如我们在本章后面将要看到的,本地方法可以从Java堆中分配内存,以充分利用垃圾回收机制,或在Java堆外面分配内存,以避开Java内存管理。C或C++的代码中在栈上分配的变量和这些语言的本地变量的语义相同。这些变量也是在它们所在的进程的栈空间中分配的。

JNI提供了和Java类型一致的类型,如表19-1所示。

表19-1:数据映射

表19-1:数据映射(续)

在复合类型中,如对象、数组和字符串等,本地代码必须显式调用转换方法对数据进行转换,这些转换方法需要使用JNIEnv指针访问。

Java端的规范

在Java类中使用本地方法之前,必须使用System.loadLibrary预先加载本地方法所在的库。通常情况下,要使用本地方法的类会静态加载这个方法。类中要被本地访问的方法会使用关键字native来声明。示例代码如下:


public class ClassWithNativeMethod {    public native double nativeMethod; // native method    static {        System.loadLibrary("sample"); // load lib called 'sample'    }    public static void main(String args) {        ClassWithNativeMethod cwnm = new ClassWithNativeMethod;        double answer = cwnm.nativeMethod; // call native method        System.out.println("Answer is : "+answer);    }}