Android 架构总览
Android 不是一个单一的操作系统,而是一个分层软件栈。从你按下电源键,到桌面出现,再到你打开一个 App,整个过程跨越了4个层次。理解这个分层架构,是后续所有 Android 原理学习的起点。
四层架构:从上到下
┌──────────────────────────────────────────────────────┐
│ Application(应用层) │
│ 你写的 App、系统自带的电话、短信、浏览器等 │
├──────────────────────────────────────────────────────┤
│ Application Framework(应用框架层) │
│ ActivityManager、WindowManager、PackageManager... │
│ 你通过 Context.getSystemService() 拿到这些服务 │
├──────────────────────────────────────────────────────┤
│ Libraries + Android Runtime(系统运行层) │
│ OpenGL ES、SQLite、WebKit、ART 虚拟机、libc... │
├──────────────────────────────────────────────────────┤
│ Linux Kernel(内核层) │
│ 驱动程序、内存管理、进程调度、Binder IPC... │
└──────────────────────────────────────────────────────┘
每层对上层提供服务,对下层透明。这是经典的「洋葱模型」——你写的代码在最外层,离硬件最远,但每一次 I/O、每一次绘制,最终都会穿透所有层次到达内核。
内核层:Linux 的定制版
Android 的基础是经过定制的 Linux 内核,承担以下核心职责:
进程和内存管理:Android 上每个 App 都是一个独立的 Linux 进程,有独立的内存空间。内核负责进程调度(给 CPU 时间)和内存分配(堆/栈)。
驱动程序:摄像头、GPU、触摸屏、WiFi 等硬件都依赖内核驱动。HAL(Hardware Abstraction Layer,硬件抽象层)是这些驱动和上层框架之间的桥梁。
Binder:这是 Android 特有的 IPC(进程间通信)机制,以一个内核驱动的形式存在(/dev/binder)。它是 Android 系统架构中最核心的创新之一,详见 Binder 原理。
Low Memory Killer:Android 基于优先级的内存回收机制。当内存不足时,内核的 LMK 驱动会按照进程的 OOM adj 值(越高越容易被杀)从后台开始杀进程,优先保护前台用户正在交互的 App。
系统运行层:ART 与 C/C++ 库
虚拟机演进:Dalvik、JIT 与 ART
Android 执行代码的容器经历了重要的演进,这里涉及三个核心名词:
1. Dalvik 虚拟机
早期(Android 5.0 之前)Android 系统的专属虚拟机。因为手机资源有限,它被设计为运行针对移动端优化过的压缩格式 .dex 文件。Dalvik 主要依赖解释器将字节码逐条翻译成机器码执行,效率较低。
2. JIT (Just-In-Time 即时编译) Dalvik 在后续版本引入了 JIT 优化(边运行边编译)。应用运行时,Dalvik 会偷偷统计这段时间内执行频繁的“热点代码”。发现热点后,JIT 会在运行时立刻将其编译成底层机器码并缓存在内存中。
- 极大优点:热点代码复用机器码,执行速度大幅提升。
- 硬伤缺陷:临时编译极其消耗 CPU(发热、掉电、偶发卡顿);且应用关闭后缓存即死,下次开应用还要再从头走一遍流程。
3. ART (Android Runtime) 与 AOT 为了根除运行时编译的代价,Android 5.0 起全面切换到全新的 ART 运行环境,核心杀手锏是引入了 AOT (Ahead-Of-Time,预编译)。
Dalvik 时代: ART 时代(Android 5.0+):
.apk(.dex 字节码) .apk(.dex 字节码)
↓ 运行时解释/JIT编译 ↓ AOT(安装时预编译为 .oat)
机器码(慢,发热耗电) 机器码(快,直接执行)
ART 不再容忍运行时边走边编,而是在下载安装 App 时一劳永逸直接把所有字节码翻译成了机器码。
- 优势:开箱即用,执行时已经是真机原生指令,启动极快且丝滑,日常运行也更为省电。
- 代价:安装大耗时;编译出的机器码体积庞大,占用更多手机闪存空间(典型的“以空间换时间”)。
💡 混合演进视角(Android 7.0+) 由于纯 AOT 导致安装奇慢且极占闪存,ART 后续又演变为 AOT + JIT + 解释器 的混合编译模式。结合 **PGO(Profile-guided Optimization,配置文件指导下的优化)**机制:
- 安装时不编译直接跑(利用解释器),实现秒安装。
- 运行时利用 JIT 机制提升阶段性能,同时追踪记录热点代码并生成 Profile 配置文件。
- 当手机闲置熄屏且插满电时,系统后台默默根据 Profile 文件,仅针对日常高频代码进行 AOT 深度编译。从而将不同编译技术的优势完美结合。
关键 C/C++ 库
| 库 | 作用 |
|---|---|
| libc(Bionic) | Android 版 C 标准库,比 glibc 更轻量 |
| OpenGL ES / Vulkan | GPU 渲染,底层支撑 Canvas / SurfaceView / RenderThread |
| SQLite | 轻量级关系型数据库,Room 的底层存储引擎 |
| WebKit/Chromium | WebView 的渲染引擎 |
应用框架层:你每天打交道的服务
应用框架层以系统服务的形式存在,运行在 system_server 进程中,通过 Binder IPC 对所有 App 提供服务:
你的 App(客户端进程) system_server 进程
┌──────────────────┐ ┌────────────────────────────┐
│ │ │ ActivityManagerService │ ← 管理Activity/Task
│ context.start │──────→│ WindowManagerService │ ← 管理窗口、Surface
│ Activity() │ Binder│ PackageManagerService │ ← 管理已安装的包
│ │←──────│ InputManagerService │ ← 分发触摸/按键事件
└──────────────────┘ │ ...(80+个系统服务) │
└────────────────────────────┘
system_server 是 Android 中最重要的进程之一,它崩溃会导致手机重启。
Zygote:所有 App 的模板
Zygote 是 App 启动速度的关键设计。它的角色是一个已预加载的 App 模板进程:
- Zygote 在系统启动时,预加载所有常用的 Android Framework 类和资源(耗时操作只做一次)
- 当用户打开一个新 App 时,系统通过
fork()复制 Zygote,得到一个新进程 fork()使用写时复制(Copy-on-Write),新进程和 Zygote 共享同一份内存页,直到某一方修改
手机启动
↓
Linux init 进程
↓
启动 Zygote
├── 预加载 Framework 类(约 4000+ 个类)
├── 预加载资源(theme、drawable、string 等)
└── 监听 Socket,等待创建 App 的请求
↓ 用户打开 App
fork()
↓
新的 App 进程(共享 Zygote 内存,零启动成本)
这就是 Android App 启动相对快速的原因:大量类加载和资源分配的工作,由 Zygote 在系统启动时一次性完成了。