设为首页 加入收藏

TOP

Android原理揭秘系列之framework本地方法注册
2014-11-24 11:33:33 来源: 作者: 【 】 浏览:0
Tags:Android 原理 揭秘 系列 framework 地方法 注册

我们知道,Android平台是Java、C/C++等多种混合语言写成的,我们在使用Android SDK提供的framework层的API来进行应用开发时通常调用的是Java方法,而实际上,这些Java API很多时候只是一个入口,方法功能的真正实现是通过JNI调用到framework层的native本地方法来实现的。比如,我们在使用Canvas的drawBitmap方法来绘制图片时,drawBitmap的真正实现就是通过JNI调用C++的同名方法来实现的。


下面,我们通过开机启动后本地方法的注册流程来具体的介绍Android API与对应本地方法究竟是如何关联起来的。


Android在开机启动后,经过一系列的加载流程,将进入\frameworks\base\cmds\ app_process\ App_main.cpp的main()方法,在main()方法中,会调用\frameworks\base\core\jni\AndroidRuntime.cpp的start()方法。事实上,Android API与本地方法的注册关联主要就是在AndroidRuntime.cpp模块里完成的。


在AndroidRuntime.cpp的start()方法中,会经过如下的调用流程,即:


void AndroidRuntime::start() --->


void AndroidRuntime::start(const char* className, const bool startSystemServer) --->


int AndroidRuntime::startReg(JNIEnv* env)


其中,startReg函数主要就是用来进行函数注册的。我们深入到该函数内部,可以看到如下的代码片段:


好了,流程介绍到这里,我们已经定位到了Android API与本地方法的注册关联的关键之处,实际上,API与本地方法的注册关键就是在此处完成的。标记为红色的register_jni_procs及其参数gRegJNI是注册关联的两大要素,下面我们对其分别作具体分析。


首先看gRegJNI的定义:


可以看到,gRegJNI是一个静态对象数组,这个对象数组实际上存储了Android framework中所有具有本地方法的java API模块的注册信息。为了理解这个RegJNIRec类型的静态数组,我们先看REG_JNI预编译宏和RegJNIRec类型的定义:


显然,带参数的REG_JNII预编译宏实际上等价于一个“{name}”,而name是一个参数;而RegJNIRec类型实际上是一个包含函数指针的结构体类型。


这样,在gRegJNI[]数组中,一个数组元素“REG_JNI(register_android_debug_JNITest),”也就等价于“{register_android_debug_JNITest },”,而这种数组定义方式的含义实际上就是把register_android_debug_JNITest这个函数指针,作为该数组元素的初始化参数,即该数组元素的mProc指针指向register_android_debug_JNITest。也就是说,gRegJNI[]数组的每个RegJNIRec结构体元素对应了一个framework子模块的本地方法注册信息,这个注册信息是通过RegJNIRec结构体元素的mProc指针来存储的。


理解静态gRegJNI数组的含义非常重要,因为其直接定义了各个framework子模块本地方法的注册关联。


下面我具体来看下gRegJNI[]数组中每个结构体元素的mProc指针存储的函数指针究竟是什么,这个函数指针指向的函数是如何工作的。我们在gRegJNI[]数组中选取大家比较熟悉的Canvas相关的数组元素REG_JNI( register_android_graphics_Canvas)为例,看看register_android_graphics_Canvas的实现,该函数的实现在frameworks\base\core\jni\android\graphics\ Canvas.cpp中:


其中REG是一个预编译宏,其定义是:


该宏最终会调用到\frameworks\base\core\jni \AndroidRuntime.cpp的registerNativeMethods 方法:


熟悉Java JNI的朋友对jniRegisterNativeMethods应该不会陌生,在这里完成了Java标准JNI的本地方法映射。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇JAVA 获取Map中的值 下一篇Android RenderScript 学习笔记

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Python爬虫教程(从 (2025-12-26 16:49:14)
·【全269集】B站最详 (2025-12-26 16:49:11)
·Python爬虫详解:原 (2025-12-26 16:49:09)
·Spring Boot Java: (2025-12-26 16:20:19)
·Spring BootでHello (2025-12-26 16:20:15)