Zygote 是 init 进程启动时创建的,通过 fork(复制进程)的形式来创建应用程序进程和 SystemServer 进程。并且,Zygote 进程在启动的时候创建 DVM 或者 ART,因此通过fork创建的应用程序进程和SystemServer进程可以在内部获取一个DVM或者ART的实例副本。


首先,Android 应用跑的的是虚拟机,虚拟机中 Java 代码的不同才造成了应用的区别,而对于基础的运行环境,要求却是一样的。

其次,Zygote 在初始化时就会创建虚拟机,同时把需要的系统类库和资源文件加载的内存中。而 Zygote 在 fork 出子进程后,这个子进程也会得到一个已经加载好基础资源的虚拟机。

这样,接下来只需要装载 APK 相关的资源就可以运行了,可以做到提升效率


放一个进程树

1
2
3
4
5
6
7
8
9
├─ /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

创建 zygotezygote_secondary 服务

1
2
3
4
5
6
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出的子进程中是共享的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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;
}

title: 浅谈 Android Zygote
date: 2022-05-10 23:31:43
updated: 2022-05-10 23:31:43
categories: 操作系统
tags:
- 虚拟机
- Android,Zygote,Java,Magisk,Zygisk,Riru

Zygote 是 init 进程启动时创建的,通过 fork(复制进程)的形式来创建应用程序进程和 SystemServer 进程。并且,Zygote 进程在启动的时候创建 DVM 或者 ART,因此通过fork创建的应用程序进程和SystemServer进程可以在内部获取一个DVM或者ART的实例副本。


首先,Android 应用跑的的是虚拟机,虚拟机中 Java 代码的不同才造成了应用的区别,而对于基础的运行环境,要求却是一样的。

其次,Zygote 在初始化时就会创建虚拟机,同时把需要的系统类库和资源文件加载的内存中。而 Zygote 在 fork 出子进程后,这个子进程也会得到一个已经加载好基础资源的虚拟机。

这样,接下来只需要装载 APK 相关的资源就可以运行了,可以做到提升效率


放一个进程树

1
2
3
4
5
6
7
8
9
├─ /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

创建 zygotezygote_secondary 服务

1
2
3
4
5
6
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出的子进程中是共享的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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;
}

title: 浅谈 Android Zygote
date: 2022-05-10 23:31:43
updated: 2022-05-10 23:31:43
categories: Android
tags:
- 虚拟机
- Android,Zygote,Java,Magisk,Zygisk,Riru

Zygote 是 init 进程启动时创建的,通过 fork(复制进程)的形式来创建应用程序进程和 SystemServer 进程。并且,Zygote 进程在启动的时候创建 DVM 或者 ART,因此通过fork创建的应用程序进程和SystemServer进程可以在内部获取一个DVM或者ART的实例副本。


首先,Android 应用跑的的是虚拟机,虚拟机中 Java 代码的不同才造成了应用的区别,而对于基础的运行环境,要求却是一样的。

其次,Zygote 在初始化时就会创建虚拟机,同时把需要的系统类库和资源文件加载的内存中。而 Zygote 在 fork 出子进程后,这个子进程也会得到一个已经加载好基础资源的虚拟机。

这样,接下来只需要装载 APK 相关的资源就可以运行了,可以做到提升效率


放一个进程树

1
2
3
4
5
6
7
8
9
├─ /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

创建 zygotezygote_secondary 服务

1
2
3
4
5
6
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出的子进程中是共享的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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;
}