Android系统Framework层源码分析.ppt

上传人:bao****ty 文档编号:131091910 上传时间:2020-05-04 格式:PPT 页数:40 大小:1.17MB
返回 下载 相关 举报
Android系统Framework层源码分析.ppt_第1页
第1页 / 共40页
Android系统Framework层源码分析.ppt_第2页
第2页 / 共40页
Android系统Framework层源码分析.ppt_第3页
第3页 / 共40页
Android系统Framework层源码分析.ppt_第4页
第4页 / 共40页
Android系统Framework层源码分析.ppt_第5页
第5页 / 共40页
点击查看更多>>
资源描述

《Android系统Framework层源码分析.ppt》由会员分享,可在线阅读,更多相关《Android系统Framework层源码分析.ppt(40页珍藏版)》请在金锄头文库上搜索。

1、Android系统Framework层源码分析 深入理解Android重难点解析 主讲人 邓凡平 大纲 一JNI重难点分析1 1注册方法的选择1 2垃圾回收二init重难点分析2 1keywords h的有趣用法2 2用好 DllMain函数 客户端Property读取的实现三Android常用类重难点分析3 1RefBase sp和wp3 2题外话 无所不用其极四Binder重难点分析4 1时空穿越魔术揭秘4 2Binder和线程的关系五Audio系统重难点分析5 1AudioTrack 方法论5 2AudioFlinger中的对象5 3AudioPolicyService实例5 4audi

2、o control block t分析5 5学习并实践DesktopCheck 大纲 接上 六Surface系统重难点分析6 1来之不易的Activity6 2乾坤大挪移 如何与SurfaceFlinger建立联系 6 3生产者和消费者之间的纽带6 4SurfaceFlinger的工作流程分析6 5Transaction分析6 6CameraService中的严重bug6 7PageFlip过程分析 一JNI重难点分析 1JNI是什么 JavaNativeInterface 2JNI在程序中有什么作用 白话 Java代码通过JNI调用Native C C 写的函数Native C C 的函数操

3、作Java层的函数 调用函数或者操作对象 1 1注册方法的选择 什么是注册 Java中定义的native函数如何找到Native层对应的函数 如何关联这两个函数 两种方法 1静态法2动态法 静态法 很简单 就是找根据一定的函数命名规则 在so库中搜索对应的函数 native init Java android media MediaScanner native 1init 静态法标准步骤 先编写Java代码 然后编译生成 class文件使用Java的工具程序javah 如javah ooutputpackagename classname 这样它会生成一个叫output h的JNI层头文件 其

4、中packagename classname是Java代码编译后的class文件 而在生成的output h文件里 声明了对应的JNI层函数 只要实现里面的函数即可 静态方法工作原理探析及其弊端 工作原理当Java层调用native init函数时 它会从对应的JNI库Java android media MediaScanner native linit 如果没有 就会报错 如果找到 则会为这个native init和Java android media MediaScanner native linit建立一个关联关系 其实就是保存JNI层函数的函数指针 以后再调用native init函

5、数时 直接使用这个函数指针就可以了 弊端 需要编译所有声明了native函数的类 只有生成了 class文件后 才能交由javah工具 默认的Native函数名字巨长 第一次调用某个native函数的时候 需要搜索so库中对应的Native函数 估计是用dlsym来获得Native函数的函数指针吧 动态方法 亲 您们从前面静态方法的介绍中看到了什么 native函数和JNI层的函数 不就是找一函数指针嘛 不找贵的 只找对的 关键数据结构 JNINativeMethod QuickQuestion 1什么时候 在哪儿注册JNINativeMethod数组 Answer 在一个特殊的native函

6、数中 Quesiton 这个特殊的native函数又是在什么时候 在哪儿注册的 Answer 鸡生蛋 蛋生鸡 当Java层通过System loadLibrary加载完JNI动态库后 紧接着会查找该库中一个叫JNI OnLoad的函数 如果有 就调用它 而动态注册的工作就是在这里完成的 1 2垃圾回收 例子 引用计数的作用呢 JNI提供三种类型的引用 足够满足亲们的需求了 LocalReference 本地引用 在JNI层函数中使用的非全局引用对象都是LocalReference 它包括函数调用时传入的jobject 在JNI层函数中创建的jobject LocalReference最大的特点

7、就是 一旦JNI层函数返回 这些jobject就可能被垃圾回收 GlobalReference 全局引用 这种对象如不主动释放 就永远不会被垃圾回收 WeakGlobalReference 弱全局引用 一种特殊的GlobalReference 在运行过程中可能会被垃圾回收 所以在程序中使用它之前 需要调用JNIEnv的IsSameObject判断它是不是被回收了 调用NewStringUTF创建一个jstring对象 它是LocalReference类型 有可能内存不够用 强烈建议 及时回收LocalRef mEnv DeleteLocalRef pathStr Soeasy NotReall

8、y JNI最好的参考资料 一切尽在不言中 JavaNativeInterfaceSpecification 从网上下载PDFJDK文档中也有 可下载chm版的 查询方便 二init重难点分析 Android对init进行了大规模改进 但还是少不了要解析配置文件init rc 所以 init的破解关键在init rc的解析代码中 解析功能在parser c 2 1keywords h的用法 两次includekeywords h Interesting includekeywords htwotimes Whatdoweget 第一次包含 得到枚举定义和一些函数 定义一个结构体数组keyword

9、 info 再次包含keywords h实际上是以枚举定义的元素为数组索引 填充keyword info数组 用新的KEYWORD宏 Result 明白了 奇技淫巧乎 2 2用好 DllMain函数 客户端Property读取的实现 Android平台提供系统级别的属性管理和控制 类比Windows平台上的 注册表 可以存储一些类似key value的键值对 作用 一般而言 系统或某些应用程序会把自己的一些属性存储在注册表中 即使下次系统重启或应用程序重启 它还能够根据之前在注册表中设置的属性 进行相应的初始化工作 Diveintocode Android想要做什么 目的 1属性区域是由ini

10、t进程创建2希望其他进程也能快速读取属性区域里的内容 Android怎么做到 方法 1属性区域创建于共享内存上2客户端进程不知不觉得映射这块内存 Diveintocode AnyQuestionsaboutinit 四Android常用类重难点分析 代码中漫天可见的RefBase spandwp到底是什么 Inmyopinion 1Refbase类似MFC的CObject 为C 对象之始祖 2sp非smartpointer 而是strongpointer wp为weakpointer 3三者协同组建AndroidC 对象生命周期的管理和控制机能 Let sdiveintocode 3 1Sam

11、pleOne 初识影子对象 A没有任何自己的功能 sp wp对象是在 中创建的 下面将先创建sp 然后创建wp 大括号结束前 先析构wp 再析构sp DiveintoCode 类A从RefBase中派生 使用的是RefBase构造函数 QuickQuestion 见到mStrong和mWeak 是否嗅到蛛丝马迹 发现影子对象成员中有两个引用计数 一个强引用 一个弱引用 如果知道引用计数和对象生死有些许关联的话 就容易想到影子对象的作用了 sp的构造 mRefs就是刚才RefBase构造函数中new出来的影子对象 原子操作 影子对象的弱引用计数加1 continueincStrong 刚才增加了

12、弱引用计数 再增加强引用计数 下面函数为原子加1操作 并返回旧值 所以c 0 x1000000 而mStrong变为0 x1000001 如果c不是初始值 则表明这个对象已经被强引用过一次了 下面这个是原子加操作 相当于执行refs mStrong 0 x1000000 最终mStrong 1 sp构造后的结果 sp的出生导致影子对象的强引用计数加1 弱引用计数加1 wp的构造 调用pA的createWeak 并且保存返回值到成员变量m refs中 调用影子对象的incWeak 将导致影子对象的弱引用计数增加1 wp构造后的结果 影子对象的弱引用计数将增加1 所以现在弱引用计数为2 而强引用计

13、数仍为1wp中有两个成员变量 一个保存实际对象 另一个保存影子对象 sp只有一个成员变量用来保存实际对象 但这个实际对象内部已包含了对应的影子对象 wp的析构 调用影子对象的decWeak 由影子对象的基类实现 把基类指针转换成子类 影子对象 的类型 这种做法有些违背面向对象编程的思想 原子减1 返回旧值 c 2 而弱引用计数从2变为1 如果c为1 则弱引用计数为0 这说明没有弱引用指向实际对象 需要考虑是否释放内存 OBJECT LIFETIME XXX和生命周期有关系 比较难分析 wp析构后 弱引用计数减1 但由于此时强引用计数和弱引用计数仍为1 所以没有对象被干掉 即没有释放实际对象和影

14、子对象占据的内存 sp的析构 注意 此时强弱引用计数都是1 下面函数调用的结果是c 1 强引用计数为0 调用前影子对象的弱引用计数为1 强引用计数为0 调用结束后c 1 弱引用计数为0 这次弱引用计数终于变为0 并且mFlags为0 mStrong也为0 注意 实际数据对象已经被干掉了 所以mRefs也没有用了 但是decStrong刚进来 的时候就保存mRefs到refs了 所以这里的refs指向影子对象 Sample1sumup RefBase中有一个隐含的影子对象 该影子对象内部有强弱引用计数 sp化后 强弱引用计数各增加1 sp析构后 强弱引用计数各减1 wp化后 弱引用计数增加1 w

15、p析构后 弱引用计数减1 完全彻底地消灭RefBase对象 包括让实际对象和影子对象灭亡 这些都是由强弱引用计数控制的 另外还要考虑flag的取值情况 当flag为0时 可得出如下结论 强引用为0将导致实际对象被delete 弱引用为0将导致影子对象被delete 生死魔咒 extendObjectLifetime 有什么用 1flags为0 强引用计数控制实际对象的生命周期 弱引用计数控制影子对象的生命周期 强引用计数为0后 实际对象被delete 所以对于这种情况 应记住的是 使用wp时要由弱生强 以免收到segmentfault信号 2flags为LIFETIME WEAK 强引用计数为

16、0 弱引用计数不为0时 实际对象不会被delete 当弱引用计数减为0时 实际对象和影子对象会同时被delete 这是功德圆满的情况 3flags为LIFETIME FOREVER 对象将长生不老 彻底摆脱强弱引用计数的控制 所以你要在适当的时候杀死这些老妖精 免得她祸害 人间 3 2题外话 无所不用其极 我的烦恼 1RefBase sp和wp 共两个文件 1千行左右的代码 不多 真正参与分析的代码应该不到400行 2判断极为复杂 打log也不方便 影响整个系统 对于这类逻辑复杂的代码 打log实为下策 冥思苦想 anygoodideas 我的解决办法 1直观想法 要是能够调试该多好 问题 部署gdbserver 太麻烦2生猛一点 代码多且简单 不存在依赖关系 不如 既然它的代码不多而且简单 那何不把它移植到台式机的开发环境下 整一个类似的RefBase呢 步骤 1用VisualStudio 编译和调试代码 2至于原子操作 Windows平台上有很直接的InterlockedExchangeXXX与之对应 3Linux平台上 不考虑多线程的话 将原子操作换成普通的非原子操作4如果你够猛

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号