Android 应用启动流程

Android 应用启动流程

一、前言

最近开始接触 Android APP 加固,涉及到 Android APP 启动流程,之前也没有较为系统的了解过,故记录一下。

二、开始

源自看雪的一篇文章,但篇文章中并没有文字解释。

┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
第一阶段:Launcher 处理
Launcher.startActivity()
↓
ActivityTaskManager.startActivity()
↓ (Binder 跨进程)
ActivityManagerService.startActivity()
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
↓
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
第二阶段:进程创建
Process.start()
↓
ZygoteProcess.start()
↓
Zygote.fork()
↓
ActivityThread.main()
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
↓
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
第三阶段:SO 加载
LoadedApk.loadLibrary()
↓
System.loadLibrary()
↓
Runtime.loadLibrary0()
↓
DexPathList.findLibrary()
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
↓
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
第四阶段:DEX 加载
PathClassLoader.loadClass()
↓
BaseDexClassLoader.loadClass()
↓
DexPathList.findClass()
↓
DexFile.loadClassBinaryName()
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
↓
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
第五阶段:Application 创建
LoadedApk.makeApplication()
↓
Instrumentation.newApplication()
↓
Application.attach()
↓
Application.onCreate()
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
↓
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
第六阶段:Activity 启动
ActivityThread.handleLaunchActivity()
↓
ActivityThread.performLaunchActivity()
↓
Instrumentation.newActivity()
↓
Activity.onCreate()
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
↓
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
第七阶段:视图绘制
Activity.setContentView()
↓
PhoneWindow.setContentView()
↓
LayoutInflater.inflate()
↓
ViewRootImpl.performTraversals()
↓
measure() → layout() → draw()
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘

下面是文字解释:

第一阶段:Launcher 处理

  • 当用户点击桌面图标时,Launcher 调用 startActivity()
  • 经过 ActivityTaskManager.startActivity(),最终跨进程调用到系统服务 ActivityManagerService.startActivity()(AMS)。
  • AMS 是 Android 应用组件的调度中心,负责决定是否需要新建进程、是否复用已有进程,并开始应用的启动流程。

第二阶段:进程创建

  • 如果应用进程尚未存在,AMS 会调用 Process.start()
  • 内部通过 ZygoteProcess.start()Zygote 进程通信,请求孵化新进程。
  • Zygote 作为系统中预加载了运行时和框架类的进程,会调用 fork() 复制出一个新的应用进程。
  • 新进程启动后执行 ActivityThread.main(),这是应用 Java 世界的入口点,启动主线程(UI 线程)的 Looper 消息循环。
  • 通过 ActivityManagerService.attachApplication() 把自己注册到 AMS,告诉系统“我进程起来了,可以调度应用逻辑了”。

第三阶段:SO 库加载

  • 在应用初始化过程中,如果代码里调用了 System.loadLibrary() 来使用 JNI,本阶段负责加载本地 .so 动态库。
  • 调用链路是:
    LoadedApk.loadLibrary()System.loadLibrary()Runtime.loadLibrary0()DexPathList.findLibrary()
  • 最终会定位到 APK 内的 lib/ 目录或系统库路径,将目标 .so 文件映射到进程空间。

第四阶段:DEX 加载

  • 应用的 Java 代码存在于 classes.dex 中,需要被类加载器解析。
  • 加载流程是:
    PathClassLoader.loadClass()BaseDexClassLoader.loadClass()DexPathList.findClass()DexFile.loadClassBinaryName()
  • 这一步负责把 .dex 文件里的字节码转换为虚拟机可执行的类对象(Class),并缓存到内存中。

第五阶段:Application 创建

  • 系统通过 LoadedApk.makeApplication() 创建应用的 Application 实例。
  • 流程:Instrumentation.newApplication() → 调用 Application.attach() → 调用 Application.onCreate()
  • 注意Application.attachBaseContext() 会在 onCreate() 之前调用,这是应用最早可以执行自定义代码的时机。很多“壳代码”或框架初始化逻辑都插在这里。

第六阶段:Activity 启动

  • AMS 调用 ActivityThread.handleLaunchActivity(),通知应用进程启动目标 Activity。
  • 内部调用 performLaunchActivity()

​ 通过 Instrumentation.newActivity() 创建 Activity 实例。

​ 调用 Activity.attach() 绑定上下文和 Window。

​ 调用生命周期方法 Activity.onCreate(),开始执行开发者写的逻辑。

第七阶段:视图绘制

  • 在 Activity 的 onCreate() 中调用 setContentView() 设置布局。
  • 流程:Activity.setContentView()PhoneWindow.setContentView()LayoutInflater.inflate() 解析 XML → 生成 View 树。
  • 之后由 ViewRootImpl.performTraversals() 触发三大绘制流程:
  1. measure() → 测量每个 View 的尺寸。
  2. layout() → 确定每个 View 的位置。
  3. draw() → 绘制到屏幕。

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1621925986@qq.com

💰

×

Help us with donation