JNI — Java Native Interface , 允许Java 语言和其它语言进行通信。在安卓系统中主要用于framework层,主要有两种方式:
(1)第一种方式:以frameworks/base/services/java/com/android/server/SystemServer.java为例:
Java文件中需要先声明native方法
/**
* Start the sensor service.
*/
private static native void startSensorService();
然后是方法的具体调用:
private void startBootstrapServices() {
......
startSensorService();
}
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
......
// Initialize native services.
System.loadLibrary("android_servers");
......
startBootstrapServices();
}
run()方法中加载了libandroid_servers.so库,执行JNI_Onload()函数(在JNI_Onload()函数中注册JNI本地函数)。
libandroid_servers.so文件的生成是在frameworks/base/services/Android.mk文件中定义的:
# native library
# =============================================================
include $(CLEAR_VARS)
LOCAL_SRC_FILES :=
LOCAL_SHARED_LIBRARIES :=
# include all the jni subdirs to collect their sources
include $(wildcard $(LOCAL_PATH)/*/jni/Android.mk)
LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES
LOCAL_MODULE:= libandroid_servers
include $(BUILD_SHARED_LIBRARY)
接下来具体看一下frameworks/base/services/core/jni/Android.mk的内容:
LOCAL_SRC_FILES += \
$(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \
$(LOCAL_REL_DIR)/com_android_server_am_BatteryStatsService.cpp \
$(LOCAL_REL_DIR)/com_android_server_am_ActivityManagerService.cpp \
$(LOCAL_REL_DIR)/com_android_server_SystemServer.cpp \
......
$(LOCAL_REL_DIR)/onload.cpp
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
frameworks/base/services \
frameworks/base/libs \
frameworks/base/libs/hwui \
......
LOCAL_SHARED_LIBRARIES += \
libandroid_runtime \
libandroidfw \
libbinder \
libcutils
......
我们可以看到在这个mk文件中引入了很多相关的库文件和cpp文件,这些文件中的方法会与JAVA中的本地方法关联起来。我们前面提到了要在JNI_Onload()函数中注册JNI的本地函数,这个JNI_OnLoad()方法就在onload.cpp文件中,如下:
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
ALOGE("GetEnv failed!");
return result;
}
ALOG_ASSERT(env, "Could not retrieve the env!");
register_android_server_ActivityManagerService(env);
register_android_server_PowerManagerService(env);
register_android_server_SerialService(env);
register_android_server_InputApplicationHandle(env);
register_android_server_InputWindowHandle(env);
register_android_server_InputManager(env);
register_android_server_SystemServer(env);
......
return JNI_VERSION_1_4;
}
在这个方法中需要先确定JNI的版本是否为JNI_VERSION_1_4并获取JNI接口函数的指针,这些操作完成后就开始通过register_android_server_~()方法将本地方法映射到libandroid_server.so库中相应的JNI本地函数上。下面我们来看看com_android_server_SystemServer.cpp中的register_android_server_SystemServer()方法。
static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsensorservice", propBuf, "1");
......
}
/*
* JNI registration.
*/
static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "startSensorService", "()V", (void*) android_server_SystemServer_startSensorService },
};
int register_android_server_SystemServer(JNIEnv* env)
{
return jniRegisterNativeMethods(env, "com/android/server/SystemServer",
gMethods, NELEM(gMethods));
}
jniRegisterNativeMethods()方法将指定类的本地方法映射到JNI的本地函数上,即SystemServer.java中的startSensorService对应的是此cpp文件中的android_server_SystemServer_startSensorService()方法,这里利用了方法名和方法签名可以唯一确定一个函数。
(2)第二种方式:以frameworks/base/core/java/com/android/internal/os/RuntimeInit.java为例:
第一步:声明对应的本地方法:
private static final native void nativeZygoteInit();
private static final native void nativeFinishInit();
private static final native void nativeSetExitWithoutCleanup(boolean exitWithoutCleanup);
第二步:具体调用:
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassL
oader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
......
nativeZygoteInit();
}
从第一种方式中我们知道需要进行注册才能使Java本地方法映射到JNI的本地方法中,这里的第二种方式就是注册的过程有些改变。
本地方法的注册是在frameworks/base/core/jni/AndroidRuntime.cpp文件中
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
REG_JNI(register_android_util_Log),
......
};
REG_JNI宏用于代码调试。
/*
* Register android native functions with the VM.
*/
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
ATRACE_NAME("RegisterAndroidNatives");
......
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
}
调用register_jni_procs()方法注册JNI本地函数。
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
return -1;
}
}
return 0;
}
下面是Java本地方法与JNI本地函数的映射信息
static const JNINativeMethod gMethods[] = {
{ "nativeFinishInit", "()V",
(void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
{ "nativeZygoteInit", "()V",
(void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
{ "nativeSetExitWithoutCleanup", "(Z)V",
(void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};
int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
{
return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
gMethods, NELEM(gMethods));
}
在register_com_android_internal_os_RuntimeInit()方法中会调用jniRegisterNativeMethods()方法将Java本地方法与JNI本地函数映射在一起(这里需要以包含待映射的Java本地方法的Java类以及包含映射信息的结构体作为参数)。