Zygote 是 init
进程启动时创建的,通过 fork
(复制进程)的形式来创建应用程序进程和 SystemServer
进程。并且,Zygote 进程在启动的时候创建 DVM 或者 ART,因此通过fork
创建的应用程序进程和SystemServer
进程可以在内部获取一个DVM或者ART的实例副本。
首先,Android 应用跑的的是虚拟机,虚拟机中 Java 代码的不同才造成了应用的区别,而对于基础的运行环境,要求却是一样的。
其次,Zygote 在初始化时就会创建虚拟机,同时把需要的系统类库和资源文件加载的内存中。而 Zygote 在 fork 出子进程后,这个子进程也会得到一个已经加载好基础资源的虚拟机。
这样,接下来只需要装载 APK 相关的资源就可以运行了,可以做到提升效率
放一个进程树
├─ /system/bin/init second_stage // init
│ ├─ zygote // 32-Bit Zygote
│ │ ├─ moe.mbr.32bit // 程序包名
│ │ │ ├─ moe.mbr.32bit // 子进程
│ ├─ zygote64 // 64-Bit Zygote
│ │ ├─ systemserver // SystemServer
│ │ │ ├─ systemserver // 子进程
│ │ ├─ com.android.chrome // 程序包名
│ │ │ ├─ com.android.chrome // 子进程
Zygote 在 init
进程中以 service 方式启动,根据 ro.zygote
引入启动脚本,安卓 5.0 开始,Zygote 有了 32/64 位的分别,在 Android 12,ro.zygote
取值有四种:
- init.zygote32.rc
- init.zygote32_64.rc
- init.zygote64.rc
- init.zygote64_32.rc
init.zygote64_32.rc
创建 zygote
和 zygote_secondary
服务
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
......
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
......
预加载系统类和资源
为了加快应用程序的启动,Android
会把系统常用的Java类
和一部分Framework
的资源放在Zygote
进程中进行预加载
。这些预加载
的类和资源在所有经zygote
进程fork
出的子进程
中是共享的。
static void preload(TimingsTraceLog bootTimingsTraceLog) {
......
// 设置软引用保护,避免被GC回收掉
beginIcuCachePinning();
......
// 加载系统类
preloadClasses();
......
// 加载系统资源
preloadResources();
......
//
nativePreloadAppProcessHALs();
......
// 加载OpenGL资源
preloadOpenGL();
// 加载一些共享so库,其实就三个:android、compiler_rt、jnigraphics
preloadSharedLibraries();
// 加载字体资源
preloadTextResources();
......
// 加载webview相关资源
WebViewFactory.prepareWebViewInZygote();
// 取消软引用保护
endIcuCachePinning();
// 初始化JCA安全相关的参数
warmUpJcaProviders();
Log.d(TAG, "end preload");
sPreloadComplete = true;
}