张绍文android开发高手课读书笔记1
本系列博文 基于是前微信高级工程师张绍文专栏 《Android开发高手课》的读书笔记。
文章所写内容是本人读完的感悟,需要原文的朋友请自行购买。
Android的开发前景如何
移动互联网发展不知不觉已经十多年过去了,“风口上的猪”也从Mobile First变成了AI First.
作为从业者的我们能很清楚的感受到移动端的招聘量变少了,但不得不提的是中高端岗位需求却更多了.
这说明移动互联网已经过了高速发展的阶段,逐渐成熟规范了。对从业者的要求也变高了,面对这种情况,
我们能做的就是不断提高自己的技术深度,同时也得扩宽技术广度.
至于一些跨平台技术,如RN,PWA,Week,以及Flutter虽然能代替一部分App开发的需求,但在最终的实现效果
上还是比不上原生开发。所以移动端的从业人员不要急着去改换门庭,应该花更多的时间去修炼内功.
另外移动端开发也不仅限于App开发,还有loT(物联网),音视频,VR/AR 等这些领域也是离不开移动互联网的.
崩溃优化
我们通常所说的崩溃就是指程序出现异常.Android下的崩溃分为java崩溃和Native崩溃。
其中java崩溃还算是比较好找的,网上也有挺多日志上报的方法.
而Native崩溃呢.一般都是因为在 Native 代码中访问非法地址,也可能是地址对齐出现了问题,或者发生了程序主动 abort,这些都会产生相应的 signal 信号,导致程序异常退出。
Android开发高手课中讲的多是Native崩溃的处理,然而我个人对这部分内容了解的也很少,所以下文多是摘取张老师专利中的重点内容。
Native入门可先看这篇博文 Android 平台 Native 代码的崩溃捕获机制及实现
Native 崩溃从捕获到解析一般要经历以下流程
- 编译端。编译 C/C++ 代码时,需要将带符号信息的文件保留下来。
- 客户端。捕获到崩溃时候,尽可能地将有用的信息写入日志,然后选择适当的时间传到服务器
- 服务端 . 读取日志,寻找合适的符号文件,生成可读的C/C++调用栈.
第三方工具中比较成熟的当属Chromium的Breakpad
在异常捕获过程中最重要的是保证在各种极端情况下生成崩溃日志,同时要保证程序不发生二次崩溃。
生成日志时会出现的问题
-
文件句柄泄漏,导致创建日志文件失败,怎么办?
我们需要提前申请文件句柄 fd 预留,防止出现这种情况。
-
因为栈溢出了,导致日志生成失败,怎么办?
为了防止栈溢出导致进程没有空间创建调用栈执行处理函数,我们通常会使用常见的 signalstack。
在一些特殊情况,我们可能还需要直接替换当前栈,所以这里也需要在堆中预留部分空间。
-
整个堆的内存都耗尽了,导致日志生成失败,怎么办?
这个时候我们无法安全地分配内存,也不敢使用 stl 或者 libc 的函数,因为它们内部实现会分配堆内存
这个时候如果继续分配内存,会导致出现堆破坏或者二次崩溃的情况.Breakpad 做的比较彻底,重新封装了Linux Syscall Support,来避免直接调用 libc。
-
堆破坏或二次崩溃导致日志生成失败,怎么办?
Breakpad 会从原进程 fork 出子进程去收集崩溃现场,此外涉及与 Java 相关的,一般也会用子进程去操作。
这样即使出现二次崩溃,只是这部分的信息丢失,我们的父进程后面还可以继续获取其他的信息。
在一些特殊的情况,我们还可能需要从子进程 fork 出孙进程。
当然对于一般的公司来说,要做这些还是有些强人所难,幸运的是市面上有合适的服务.比如腾讯的Bugly,阿里的啄木鸟平台,网易云捕等.
在热修复流行的当下,就算线上发送了一些崩溃,也可能通过打补丁来达到在线修复。但是如果崩溃发生在启动的时,在热修复代码执行之前,那就糟糕了。所以一些大公司的产品还会有"安全模式"来保障启动流程.
安全模式
在App热修复中有一个特殊情况,就是应用在启动阶段crash,根本启动不了,热修复就难以奏效。这个时候可以采取一种安全模式的启动方式.

简单来说,就是增加一个flag启动标记位,用来标记用户是否连续两次启动失败,这个时候就会进入安全模式进入修改阶段.修复的方式
- 自修复,清空业务数据,尝试启动
- 热修复,根据配置文件来判断是否修改
- 重制为初始安装状态,将Document、Library、Cache三个根目录清空
详细可看 安全模式:天猫App启动保护实践
如何快速定位崩溃
发生崩溃就一定会有崩溃信息,那么我们应该看的是那部分信息?
1.崩溃基本信息
进程名、线程名。崩溃的进程是前台进程还是后台进程,崩溃是不是发生在 UI 线程。
崩溃的堆栈和类型.是java崩溃,Native崩溃,还是ANR.是自己的代码问题,还是系统的代码问题.
2.系统和应用的运行日志.
系统的event logcat会记录App运行的一些基本情况,记录在/system/etc/event-log-tags 中。
system logcat:
10-25 17:13:47.788 21430 21430 D dalvikvm: Trying to load lib ...
event logcat:
10-25 17:13:47.788 21430 21430 I am_on_resume_called: 生命周期
10-25 17:13:47.788 21430 21430 I am_low_memory: 系统内存不足
10-25 17:13:47.788 21430 21430 I am_destroy_activity: 销毁 Activty
10-25 17:13:47.888 21430 21430 I am_anr: ANR 以及原因
10-25 17:13:47.888 21430 21430 I am_kill: APP 被杀以及原因
3.机型、系统、厂商、CPU、ABI、Linux 版本等
上述这些数据可用作横向比较,你经常会发现某个问题只会在特定的情况下出现。
4.设备状态 是否root,是否是模拟器.有些问题是由Xposed 或多开软件造成
5.内存信息,考虑一些内存不足的崩溃是否多发生在低内存的手机上.
6.自定义的应用信息
这部分信息主要用来辅助定位崩溃位置.可以记录崩溃发生的位置,某个activity;还可以记录发生崩溃之前的几个操作步骤,便于复现崩溃场景.
解决崩溃
1.优先级: 优先解决Top 崩溃或者对业务有重大影响;其次简单易排查的java崩溃,疑难杂症放到最后
2.尝试复现:针对疑难杂症,可以通过早先在日志中自定义的应用信息来复现崩溃过程
3.着眼硬件:排查是否是手机系统,内存,机型引起的。
4.系统错误:有些问题是Android系统不同版本之间存在的问题。
最后,给自己公众号打个广告,【码农的唠叨】聊技术,聊热文,聊互联网趣事,也发唠叨
