type
status
date
slug
summary
tags
category
icon
password
💡
本文为学习apk加固的前置知识,here we go!

app两种启动方式

  1. 冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,然后再根据启动的参数,启动对应的进程组件,这个启动方式就是冷启动。
  1. 热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动对应的进程组件,这个方式叫热启动。
而我们讨论的app启动流程,是针对冷启动的

冷启动流程(app启动流程)

notion image

图转文字

  1. 用户点击应用图标
    1. ①点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求
  1. System Server进程处理请求
      • ActivityManagerService (AMS) 负责解析Intent、验证权限、创建目标应用进程。
      • PackageManagerService (PMS) 提供应用包信息(如AndroidManifest.xml)。
  1. Zygote进程孵化应用进程
    1. ②system_server进程接收到请求后,通过socket向zygote进程发送创建进程的请求
      ③Zygote进程fork出新的子进程,即App进程
      • 新进程加载目标应用的代码和资源。
  1. 应用进程初始化
    1. ④App进程,通过Binder IPC向sytem_server进程发起attachApplication请求
      ⑤system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求
      ⑥App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息
      ⑦主线程在收到Message后,通过反射机制创建目标Activity,并回调Activity.onCreate()等方法
  1. UI渲染完成
    1. ⑧App正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面,通过SurfaceFlinger合成帧并显示。

核心进程及通信方式

(1) Launcher进程 → System Server(AMS/PMS)
  • 通信方式:Binder(基于AIDL)
  • 原因
    • Binder是Android默认的高效IPC机制,支持同步调用和复杂数据传输。
    • Launcher与AMS/PMS属于不同进程,需跨进程调用系统服务。
(2) System Server(AMS) → Zygote
  • 通信方式:Unix Domain Socket
  • 原因
    • Zygote在开机时通过Socket监听请求(避免依赖Binder的递归初始化问题)。
    • Socket适合单向、批量数据传输(如传递应用启动参数)。
(3) System Server(AMS) → 应用进程
  • 通信方式:Binder
  • 原因
    • AMS需要持续管理应用生命周期(如暂停/销毁Activity),Binder支持双向通信。
    • 应用进程通过IApplicationThread(Binder接口)回调AMS。
(4) 应用进程 → SurfaceFlinger
  • 通信方式:Binder + Shared Memory(ASHMEM)
  • 原因
    • Binder传递UI元数据(如窗口属性)。
    • Shared Memory(通过Surface)高效传输图像数据,避免拷贝开销。

热启动流程

  1. 用户点击应用图标或返回应用
      • Launcher或Recent Tasks通过startActivity()发起启动请求。
  1. System Server(AMS)检查进程状态
      • AMS发现目标应用进程仍存活,直接复用该进程。
  1. 恢复Activity栈
      • AMS通过Binder通知应用进程恢复之前的Activity(而非创建新实例)。
  1. UI渲染
      • 应用主线程重新执行onResume()、测量/布局/绘制,并显示界面。

深入理解安卓应用程序启动流程

还是以冷启动来看,copy东方玻璃大佬的文章
以上流程的核心可总结为三个部分,后续将围绕这三部分展开:
  1. 创建应用程序进程
  1. 创建Application
  1. 启动根Activity

创建应用程序进程简介

要想启用一个Android应用程序,要保证该程序所需的应用程序进程存在.
当点击应用程序图标后,触发Launcher.onClick方法,经过一系列方法调用后,在ActivityStackSupervisor.startSpecificActivityLocked中会判断当前应用程序进程是否存在.
若不存在则调用AMS代理类ActivityManagerProxy的startProcessLocked请求AMS创建应用程序进程,AMS接收Launcher的请求后又向Zygote发送请求.
这一过程可分为两部分:
  • AMS向Zygote发送启动应用程序进程的请求
  • Zygote接收AMS的请求并创建应用程序进程
AMS向Zygote发送启动应用程序进程的请求的流程如下:
Launcher请求AMS,AMS请求Zygote,通过ZygoteInit.main进入Zygote
notion image
Zygote接收AMS的请求并创建应用程序进程的流程如下:
  1. 在进行一系列处理后进入ZygoteConnection.handleChildProc,该函数内部配置子进程的初始环境后并调用ZygoteInit.zygoteInit初始化应用程序进程
  1. ZygoteInit.zygoteInit中调用ZygoteInit.nativeZygoteInit启动了应用程序进程的Binder线程池,使得进程可以进行Binder通讯,之后调用RuntimeInit.applicationInit
      • Binder 线程池:Server 端通过线程池处理多个 Client 的并发请求,避免主线程阻塞
  1. RuntimeInit调用invokeStaticMain并抛出Zygote.MethodAndArgsCaller异常,经过异常处理清空设置过程中的堆栈帧后,调用主线程管理类ActivityThread的main方法,至此,应用程序进程被成功创建
notion image

创建Application简介

ActivityThread.main进行部分初始化配置后,创建并启动主线程消息循环管理类Looper用于进行消息处理,并且调用attach方法通知AMS附加自身ApplicationThread类.
AMS中通过ApplicationThread的代理类IApplicationThread发送BIND_APPLICATION消息到应用程序的消息队列.
之后应用程序主线程管理类ActivityThread的handleMessage处理该消息,并调用handleBindApplication创建Application并绑定,主要执行以下4个步骤:
  1. ActivityThread.getPackageInfoNoCheck
    1. 创建LoadedApk对象,设置ApplicationInfo和ClassLoader并加入mPackages中,该对象是应用程序apk包的管理类
      • LoadedApk:每个应用对应一个LoadedApk实例,包含:
        • APK 的资源路径、证书信息、权限等
        • 应用的ClassLoader(默认是PathClassLoader
        • 缓存的资源和类信息
  1. ContextImpl.createAppContext
    1. 创建应用程序的上下文环境Context类
  1. LoadedApk.makeApplication(创建 Application 实例)
    1. 创建Application,并调用Application.attachBaseContext方法
  1. Instrumentation.callApplicationOnCreate
    1. 调用Application.onCreate方法
至此,Application创建完成,以上流程如图所示:
notion image

启动根Activity简介

经过以上步骤后,创建了应用程序进程和对应的Application,回到Launcher请求AMS过程,在ActivityStackSupervisor.startSpecificActivityLocked中调用了ActivityStackSupervisor.realStartActivityLocked,其内部通过调用ApplicationThread.scheduleLaunchActivity通知应用程序启动Activity.
ApplicationThread通过sendMessage向H类(应用程序进程中主线程的消息管理类)发送H.LAUNCH_ACTIVITY消息,H.handleMessage接收到消息后调用ActivityThread.handleLaunchActivity将控制权转移给ActivityThread.
handleLaunchActivity调用performLaunchActivity执行启动Activity的步骤:
  1. 获取Activity信息类ActivityInfo
  1. 获取Apk文件描述类LoadedApk
  1. 为Activity创建上下文环境
  1. 获取Activity完整类名并通过ClassLoader创建Activity实例
  1. 调用LoadedApk.makeApplication
    1. 这一步需要解释,Application类是Android的应用程序描述类,每个应用程序只有一个全局单例的Application.
      此处调用makeApplication时,由于ActivityThread.main中已经创建Application,所以会直接返回已创建的Application.
      而performLaunchActivity用于启动任意Activity,根Activity必定使用ActivityThread.main创建的Application,但其他Activity可能在子进程中运行,所以此处的调用主要用于处理一般Activity.
  1. 调用Activity.attach初始化Activity
  1. 调用Instrumentation.callActivityOnCreate启动Activity
以上流程如图所示:
notion image
经过以上步骤后,安卓应用程序正式启动(根Activity启动),其中最值得关注的便是ActivityThread,Application和LoadedApk类.
  1. ActivityThread是安卓应用程序进程的主线程管理类
    1. 保存了很多关键信息,通过该类可以反射获取应用程序进程的Application和LoadedApk.
  1. Application用于描述当前的应用程序
    1. 应用程序启动过程中,Application实例是最先创建的,早于应用程序启动以及任何Activity或Service,它的生命周期是整个应用程序中最长的,等于应用程序的生命周期.
      安卓应用程序开发时,可通过继承该类并重写attachBaseContext和onCreate方法进行部分资源的初始化配置.如果被保护程序没有指定自定义的Application,使用系统创建的默认Application即可;如果存在自定义的Application,则脱壳程序需要替换.
  1. LoadedApk用于描述当前应用程序对应的APK文件
    1. 其mClassLoader字段保存了当前APK对应的类加载器,mApplication字段保存了当前Application.
dex文件结构JNI学习
Loading...
Sh4d0w
Sh4d0w
漫长学习路ing
最新发布
360加固复现学习
2025-6-15
java反射机制
2025-6-14
classLoader机制
2025-6-14
dex文件结构
2025-6-14
APP启动流程
2025-6-14
JNI学习
2025-6-14
公告
Welcome to Sh4dw’s blog!
敬请指导,Q 467194403