前言
当某个应用组件启动且该应用没有运行其他任何组件时,Android 系统会使用单个执行线程为应用启动新的 Linux 进程。默认情况下,同一应用的所有组件在相同的进程和线程(称为“主”线程)中运行。 如果某个应用组件启动且该应用已存在进程(因为存在该应用的其他组件),则该组件会在此进程内启动并使用相同的执行线程。 但是,您可以安排应用中的其他组件在单独的进程中运行,并为任何进程创建额外的线程。
进程
每个App在启动前必须先创建一个进程,该进程是由Zygote fork出来的,进程具有独立的资源空间,用于承载App上运行的各种Activity/Service等组件。大多数情况一个App就运行在一个进程中,除非在AndroidManifest.xml中配置Android:process属性,或通过native代码fork进程。
进程是能在系统中独立运行并作为资源分配的基本单位,是CPU分配资源的最小单位,它包括独立的地址空间,资源以及一至多个线程。
线程
线程是进程中的一个实体,是CPU调度的最小单位,没有独立空间地址,多线程共享所属进程的空间地址,线程主要负责是CPU执行代码的过程
APP应用启动时,系统会为应用创建一个名为“主线程”的执行线程。
进程创建流程图
- 进程创建起点,Process.start,然后告知ZygoteProcess执行启动,它会构造socket通道最后将构造指令及参数发送给zygote进程
- zygote进程,socket会循环监听请求,在接受请求后,会封装好构建进程参数通过Zygote.forkAndSpecialize及其native方法fork出一个子进程
- 子进程fork后,会进行一系列fork后处理事项及Runtime的init初始化工作,最后回调到子进程的zygote.runSelectLoop方法抛出异常走到ActivityThread.main方法,进入子进程世

进程创建代码分析
进程创建入口
Process.java
1 | public static final ProcessStartResult start(final String processClass, |
进程创建参数准备
主要工作是生成argsForZygote数组,该数组保存了进程的uid、gid、groups、target-sdk、nice-name等一系列的参数。
ZygoteProcess.java
1 |
|
连接Zygote服务,写入创建指令并获取返回结果
ZygoteProcess.java
通过socket向Zygote进程发送消息,从而唤醒Zygote进程,来响应socket客户端的请求
1 | private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { |
Zygote接收客户端Socket请求
ZygoteInit.java
1 | public static void main(String argv[]) { |
ZygoteServer
- 客户端通过openZygoteSocketIfNeeded()来跟zygote进程建立连接。zygote进程收到客户端连接请求后执行accept();然后再创建ZygoteConnection对象,并添加到fds数组列表;
- 建立连接之后,可以跟客户端通信,进入runOnce()方法来接收客户端数据,并执行进程创建工作
1 | void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller { |
java层fork参数准备
ZygoteConnection.java
1 | boolean runOnce(ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller { |
nativeFork前准备
Zygote.java
调用虚拟机执行preFork工作:停止Daemon子线程、等待所有子线程结束、完成gc堆的初始化工作
1 | public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags, |
调用native的fork方法
com_android_internal_os_Zygote.cpp
1 | static jint com_android_internal_os_Zygote_nativeForkSystemServer( |
fork
fork()采用copy on write技术,这是linux创建进程的标准方法,调用一次,返回两次,返回值有3种类型。父进程中,fork返回新创建的子进程的pid;子进程中,fork返回0;当出现错误时,fork返回负数。(当进程数超过上限或者系统内存不足时会出错)
fork()的主要工作是寻找空闲的进程号pid,然后从父进程拷贝进程信息,例如数据段和代码段,fork()后子进程要执行的代码等。 Zygote进程是所有Android进程的母体,包括system_server和各个App进程。zygote利用fork()方法生成新进程,对于新进程A复用Zygote进程本身的资源,再加上新进程A相关的资源,构成新的应用进程A。

1 | int fork() { |
执行子进程fork完成后的hooks
1 | private static void callPostForkChildHooks(int debugFlags, boolean isSystemServer, String instructionSet) { |
dalvik_system_ZygoteHooks.cc
设置新进程的主线程id,重置gc性能数据,设置信号处理函数等功能。
1 | static void ZygoteHooks_nativePostForkChild(JNIEnv* env, jclass, jlong token, jint debug_flags, jstring instruction_set) { |
Runtime.cc
创建Java堆处理的线程池、设置信号处理函数
1 | void Runtime::DidForkFromZygote(JNIEnv* env, NativeBridgeAction action, const char* isa) { |
VM_HOOKS的fork后续操作
ZygoteHooks.java
主要功能是在fork新进程后,启动Zygote的4个Daemon线程,java堆整理,引用队列,以及析构线程。
1 | public void postForkCommon() { |
新进程创建后的初始化事项
ZygoteConnection.java
1 | private void handleChildProc(Arguments parsedArgs, |
RuntimeInit.java
- commonInit,初始化时区、代理、异常捕获处理类等
- nativeZygoteInit,启动binder相关初始化
- applicationInit,app相关初始化,最后抛出异常回到runSelectLoop,该方法的参数m是指main()方法, argv是指ActivityThread. 根据前面的中可知,下一步进入caller.run()方法,也就是执行ActivityThread的main方法。
1 | public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) |
最后执行ActivityThread的main方法
ActivityThread.java
1 | public static void main(String[] args) { |
推荐阅读:图形系统总结


