Android 中的两种优化
Java 崩溃
Java 崩溃就是在 Java 代码中,出现了未捕获异常,导致程序异常退出。
Native 崩溃
一般都是因为在 Native 代码中访问非法地址,也可能是地址对齐出现了问题,或者程序主动 abort,这些都会产生相应的 signal 信息,导致程序异常退出。
崩溃现场
1.崩溃信息
- 进程名、线程名。崩溃的进程是前台进程还是后台进程,崩溃是不是发生在 UI 线程。
- 崩溃堆栈和类型。崩溃是属于 Java 崩溃、Native 崩溃,还是 ANR。
2.系统信息
- Logcat。这里包括应用、系统的运行日志。记录在文件 /system/etc/event-log-tags 中。
- 机型、系统、厂商、CPU、ABI、Linux 版本等。
- 设备状态:是否 root、是否是模拟器。一些问题是由 Xposed 或多开软件造成,对这部分问题我们要区别对待。
3.内存信息
- 系统剩余内存。关于系统内存状态,可以直接读取文件 /proc/meminfo。当系统可用内存很小(低于 MemTotal 的 10%)时,OOM、大量 GC、系统频繁自杀拉起等问题都非常容易出现。
- 应用使用内存。包括 Java 内存、RSS(Resident Set Size)、PSS(Proportional Set Size),我们可以得出应用本身内存的占用大小和分布。PSS 和 RSS 通过 /proc/self/smap 计算,可以进一步得到例如 apk、dex、so 等更加详细的分类统计。
- 虚拟内存。虚拟内存可以通过 /proc/self/status 得到,通过 /proc/self/maps 文件可以得到具体的分布情况。
4.资源信息
- 文件句柄 fd。文件句柄的限制可以通过 /proc/self/limits 获得,一般单个进程允许打开的最大文件句柄个数为 1024。但是如果文件句柄超过 800 个就比较危险,需要将所有的 fd 以及对应的文件名输出到日志中,进一步排查是否出现了有文件或者线程的泄漏。
- 线程数。当前线程数大小可以通过上面的 status 文件得到,一个线程可能就占 2MB 的虚拟内存,过多的线程会对虚拟内存和文件句柄带来压力。根据我的经验来说,如果线程数超过 400 个就比较危险。需要将所有的线程 id 以及对应的线程名输出到日志中,进一步排查是否出现了线程相关的问题。