Zygote简介
Zygote作为Android核心进程三剑客(Init,SystemServer,Zygote)之一,本身是一个Native程序,一堆C代码,与驱动,内核无关。核心功能是初始化Android进程运行的环境,主要是由Init进程在rc文件中以Service的形式启动的。
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
不同设备会有不同版本的RC文件,不过核心功能大同小异。通过import /init.${ro.zygote}.rc 来引入。
Zygote核心功能
一张图概括Zygoute的核心功能
Zygote源码目录在/frameworks/base/cmds/app_process/app_main.cpp,一个C++文件。根据流程图显示,Zygote的核心功能分布在C++ 层和Java层。下面依次简单介绍。
1、分析启动参数
rc脚本中以service形式启动zygote,参数格式就是 app_process [虚拟机参数] 运行目录 参数 [Java类]
- 虚拟机参数:以符号
-开头,启动虚拟机时传递给虚拟机 - 运行目录:程序运行目录,一般都是/system/bin
- 参数:以符号
--开头,参数--zygote表示要启动zygote进程。参数--application表示要以普通进程执行Java代码。 - Java类:将要执行Java类,必须要有一个静态方法main。使用参数
--Zygote时不会执行这个类,而是固定执行ZygoteInit类。
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
2、初始化AndroidRuntime
AndroidRuntime是底层非常重要的一个类,负责启动虚拟机和Java线程,一个进程中只有一个实例对象。像老夫这样的菜鸟经常遇到AndroidRuntime的报错(狗头!!!)Zygote运行Java代码之前,需要初始化整个Java环境,所以在Zygote代码末端,AndroidRuntime的start方法执行了整个过程。
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
start方法会获取系统目录,基本默认是/system,创建虚拟机,注册JNI函数,初始化好了Java环境,就会调用到核心的Java类ZygoteInit的main方法。根据流程图显示,从此处进入Java环境。
ZygoteInit初始化任务
Zygote来这里只做三件事:公平,公平,还是他妈的公平......
1、preload方法初始化系统资源,包括预加载类,Framework资源和OpenGL资源。这就是面试官的装逼问题,为什么APP进程要从Zyogte进程Fork?,因为这些预加载资源和类,已经初始化好了,根据Fork机制可以继承,大大节省了启动时间。
2、调用startSystemServer方法启动SystemServer进程,这个进程是Android开发们的最爱了。
3、最后创建本地socket,并且进入Loop,随时响应socket消息,如AMS启动APP进程。Linux的一些知识点有助于理解Android系统原理,简单列举Fork,Socket,Select,Epoll等机制。
PS:Init进程和Zygote进程创建进程有些区别,exec其实就是Linux启动程序的方式,所以很多守护进程本质就是Linux中运行一个bin文件。而load的方式其实就是Linux通过fork的方式初始化一个进程,借用JVM去加载一堆Java代码。
Zygote启动APP进程
前期的初始化工作完毕后,Zygote最后的任务就是化作守护进程,去Fork出APP进程。在Android系统中,有很多原因导致系统去启动一个新的进程,比如启动Activity,AMS最终还是会通过Socket通信,向Zygote请求创建进程。所以前面介绍的ZgoteInit类创建本地socket就是有此作用,开启loop监听socket事件,接受连接请求,并且接受socket消息等一系列逻辑。详情后续专门通过APP进程启动流程讲解。
预加载资源
Zygote的预加载资源,主要包含系统Java类的jar包,资源文件,核心lib库,这些都是与APP进程共享,所以省去了大量重新加载的时间。
源码好无聊,有兴趣自己去看吧,说了那么多,面试的时候你知道该怎么吹了吧......