《Android的设计与实现:卷I》——第1章 2.2JNI框架层实例分析

    xiaoxiao2021-04-18  190

    2.2 JNI框架层实例分析

    框架层大量使用了JNI技术来完成对系统运行库的调用。深入理解JNI对分析框架层代码十分有用。本节将以框架层的实例详细讲解JNI编程的三个步骤。

    在Android应用程序开发中,一般是调用应用框架层的android.util.Log.java提供的Java接口来使用日志系统。比如我们会写如下代码输出日志:Log.d(TAG,"debug log");

    这个Java接口其实是通过JNI调用系统运行库(即本地库)并最终调用内核驱动程序Logger把Log写到内核空间中的。在Android中, Log系统十分通用,而且其JNI结构非常简洁,很适合作为JNI入门的例子。本节就以它为例贯穿始终,详细讲解JNI各部分的内容。

    本节所涉及的文件包括:frameworks/base/core/jni/android_util_Log.cpp(JNI层实现代码)frameworks/base/core/java/android/util/Log.java(Java层代码)libnativehelper/include/nativehelper/jni.h(JNI规范的头文件)libnativehelper/include/nativehelper/JNIHelp.h libnativehelper/JNIHelp.cppframeworks/base/core/jni/AndroidRuntime.cpp读者可以在Source Insight或者Eclipse中打开这几个文件为下面的分析做准备。

    2.2.1 Log系统Java层分析

    首先看Log系统Java层部分。打开Log.java文件,可以看到这里面只定义了isLoggable和println_native两个Native方法,其代码如下:package android.util;public final class Log { …… public static int d(String tag, String msg) {

    //使用Native方法打印日志。LOG_ID_MAIN表示日志ID,有4种:main、radio、events、system return println_native(LOG_ID_MAIN, DEBUG, tag, msg);

    } ……

    //声明Native方法isLoggable public static native boolean isLoggable(String tag, int level);

    …… /** @hide / public static final int LOG_ID_MAIN = 0; /** @hide / public static final int LOG_ID_RADIO = 1; /** @hide / public static final int LOG_ID_EVENTS = 2; /** @hide / public static final int LOG_ID_SYSTEM = 3;

    //声明Native方法println_native

    /** @hide / public static native int println_native(int bufID,

    int priority, String tag, String msg);

    }

    Java层需要做的就这么简单。只需要声明方法为native而无需实现,就可以直接调用,不会出现任何编译错误。接下来看JNI层的实现代码。

    2.2.2 Log系统的JNI层

    JNI层是实现Java层方法最关键的部分。还是以Log系统为例讲解JNI层是如何实现Java层声明的Native方法的。不熟悉JNI的读者可以根据包名和类名定位JNI层文件,对于Log类,其对应的JNI文件是android_util_Log.cpp。打开android_util_Log.cpp文件,其代码如下:

    从这里以看出,JNI层的实现方法只是根据一定的规则与Java层声明的方法做了一个映射,然后可以通过使用本地库函数或JNIEnv提供的JNI函数响应Java层调用。读者只需要熟悉这部分代码的大体结构和功能即可,后续章节将会详细介绍这部分内容。

    相关资源:《Android的设计与实现 第一卷》(完整书签)

    最新回复(0)