Zygote进程
zygote进程运行时,会初始化Art(或者Dalvik)虚拟机,并启动它。Android的应用程序是由Java编写的,它们不能直接以本地进程的形式运行在linux上,只能运行在虚拟机中。并且,每个应用程序都运行在各自的虚拟机中,如果应用程序每次运行都要重新初始化并启动虚拟机,这个过程会耗费相当长时间。因此,在Android中,应用程序运行前,zygote进程通过共享已运行的虚拟机的代码与内存信息,缩短应用程序运行所耗费的时间。并且,它会事先将应用程序要使用的Android Framework中的类和资源加载到内存中,并组织形成所用资源的链接信息。新运行的Android应用程序在使用所需资源时不必每次重新形成资源的链接信息,这回节省大量时间,提高程序运行速度。
那么,在Linux系统中创建并运行一个进程,与在Android系统中通过zygote来创建并运行一个应用程序,两者究竟有何不同呢?
以下图片均参考自《Android框架揭秘》一书(实在不想自己画了 0.0)
如上图所示,父进程A调用fork()函数创建新的子进程A’。新创建的进程A’共享父进程的内存结构信息与库连接信息(COW 写时拷贝技术)。而后子进程A’调用exec(‘B’),将新进程B的代码加载到内存中。此时,将重新分配内存(因为之前是共享的),以便运行被装载的B程序,接着形成新的库连接信息,以供B进程单独使用。
如上图所示,zygote进程调用fork()函数创建出zygote’子进程,子进程zygote’ 共享父进程zygote的代码区与链接信息。注意,新的Android应用程序A 并非通过exec() 来重新装载已有进程的代码区,而是动态的加载到复制的虚拟机上(虚拟空间的复制,物理空间还是同一个)。而后,zygote’进程将执行流程交给应用程序A类的方法,Android应用程序开始运行。新生成的应用程序A会使用已有zygote进程的库与资源的链接信息,所以运行速度很快。
如上图所示,zygote启动后,初始化并运行art(或者dalvik)虚拟机,而后将需要的类与资源加载到内存中。随后调用fork()创建出zygote’子进程,接着zygote’子进程动态加载并运行Android应用程序A。运行的应用程序A会使用zygote已经初始化并启动运行的虚拟机代码,通过使用已记载至内存中的类与资源来加快运行速度。
COW (Copy on write)
在创建新进程后,新进程会共享父进程的内存空间,即新的子进程会复制所有与父进程内存空间相关的信息并使用它。COW就是针对内存复制的一种技术。一般来说,复制内存的开销非常大,因此创建的子进程在引用父进程的内存空间时,不要进行复制,而要直接共享父进程的内存空间。而当需要修改共享内存中的信息时,子进程才会将父进程中相关的内存信息复制到自身的内存空间,并进行修改,这就是COW(Copy on write)技术。
Zygote进程源码分析
由app_process运行ZygoteInit class
zygote由java编写而成,不能直接由init进程启动运行。若想执行zygote类,必须先创建虚拟机,然后在虚拟机上运行ZygoteInit类。执行这一任务的就是app_process程序。
下面我们开始分析zygote进程的启动流程:
/system/core/rootdir/init.rc
import /init.$(ro.zygote).rc
如果是64位系统,$(ro.zygote)的值为"zygote64"
/system/core/rootdir/init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
...
class main
user root
socket zygote stream 660 root system //创建/dev/socket/zygote套接字
...
init进程解析上面的init.zygote64.rc文件后,会执行/system/bin/app_process64进程,并且生成了/dev/socket/zygote套接字,ZygoteInit会用该套接字来接收AMS发来的创建新应用程序的请求。
init进程分析并执行rc文件流程可以看看我的上一篇文章Init进程的启动流程。
app_process64程序的main函数入口如下:
frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
......
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
......
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
......
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
}
......
}
......
if (zygote) {
//zygote进程
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
//普通java进程
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
}
}
如果是zygote进程就走ZygoteInit代码,如果是普通java进程就走RuntimeInit代码,例如常用的am命令,/system/bin/am实际上是一个shell脚本,查看里面的代码可知是通过app_process来启动普通java进程,然后和AMS进行通信。
frameworks/base/core/jni/AndroidRuntime.cpp
//AppRuntime继承自AndroidRuntime
void AndroidRuntime::start(const char* className, const Vector
{
/* start the virtual machine */
JniInvocation jni_invocation;
// ① 加载指定的虚拟机的库(art或者dalvik)
jni_invocation.Init(NULL);
JNIEnv* env;
// ② 创建java虚拟机
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
// ③ 注册JNI函数
if (startReg(env) < 0) {
return;
}
......
// ④ 正式进入java的世界,调用ZygoteInit.java的main方法
jclass startClass = env->FindClass(slashClassName);
......
jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
......
env->CallStaticVoidMethod(startClass, startMeth, strArray);
......
}
①: 加载虚拟机的库(art或者dalvik),并且函数指针指向库对应的函数(如:JNI_CreateJavaVM函数)
libnativehelper/JniInvocation.cpp
bool JniInvocation::Init(const char* library) {
//获取要加载库的名称
library = GetLibrary(library, buffer);
//动态加载对应的虚拟机库
handle_ = dlopen(library, RTLD_NOW);
......
//JNI_CreateJavaVM_函数指针指向虚拟机库中的JNI_CreateJavaVM函数
if (!FindSymbol(reinterpret_cast
"JNI_CreateJavaVM")) {
return false;
}
.......
return true;
}
GetLibraray()函数获取动态库的名称(libart.so或者libdalvik .so),dlopen()函数动态加载虚拟机库,RTLD_NOW表示返回之前立即链接所有未定位的符号,FindSysmbol()函数指针指向对应的函数。
libnativehelper/JniInvocation.cpp
static const char* kLibrarySystemProperty = "persist.sys.dalvik.vm.lib.2";
static const char* kDebuggableSystemProperty = "ro.debuggable";
static const char* kDebuggableFallback = "0"; // Not debuggable.
static const char* kLibraryFallback = "libart.so";
const char* JniInvocation::GetLibrary(const char* library, char* buffer) {
char debuggable[PROPERTY_VALUE_MAX];
//获取"ro.debuggable"的属性值
property_get(kDebuggableSystemProperty, debuggable,kDebuggableFallback);
if (strcmp(debuggable, "1") != 0) {
//如果不是debug设备,library的值为"libart.so"
library = kLibraryFallback;
} else {
//如果是debug设备,library的值为"persisit.sys.dalvik.vm.lib.2"的属性值
property_get(kLibrarySystemProperty, buffer, kLibraryFallback);
}
return library;
}
: 创建java虚拟机
frameworks/base/core/jni/AndroidRuntime.cpp
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
JavaVMInitArgs initArgs;
......
initArgs.version = JNI_VERSION_1_4;
initArgs.options = mOptions.editArray();
initArgs.nOptions = mOptions.size();
initArgs.ignoreUnrecognized = JNI_FALSE;
......
//创建java虚拟机
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
ALOGE("JNI_CreateJavaVM failed\n");
return -1;
}
return 0;
}
JNI_CreateJavaVM()是JniInvocation.cpp中的函数,会调用到①中所说的JNI_CreateJavaVM_()函数指针,最后调用到相应虚拟机动态库中的JNI_CreateJavaVM()函数,创建对应的虚拟机。initArgs表示传入的虚拟机参数。
③: 注册JNI本地函数
我们先来熟悉一下几个数据结构:
frameworks/base/core/jni/AndroidRuntime.cpp
#define REG_JNI(name) { name }
struct RegJNIRec {
int (*mProc)(JNIEnv*);
};
......
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
REG_JNI(register_android_util_Log),
......
};
gRegJNI是RegJNIRec结构体数组,然后数组通过REG_JNI宏定义初始化。例如gRegJNI第一个元素的初始化,等同于:
gRegJNI[0] = {register_com_android_internal_os_RuntimeInit};
那么gRegJNI[0]中RegJNIRec结构体的mProc函数指针就指向上面的函数register_com_android_internal_os_RuntimeInit,数组中的其它元素也同理。下面我们继续分析JNI本地函数的注册。
frameworks/base/core/jni/AndroidRuntime.cpp
int AndroidRuntime::startReg(JNIEnv* env)
{
......
//注册JNI本地函数,将gRegJNI数组传入
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
return -1;
}
......
return 0;
}
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
//遍历执行gRegJNI数组中元素的mProc函数
//(mProc是函数指针,数组初始化的时候已经指向指定的函数)
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) {
return -1;
}
}
return 0;
}
startReg会调用register_jni_procs遍历调用gRegJNI数组中的mProc函数,以第一个元素为例,gRegJNI[0].mProc(env)由上面的分析可知调用的实际是register_com_android_internal_os_RuntimeInit(env)函数。
frameworks/base/core/jni/AndroidRuntime.cpp
int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
{
const JNINativeMethod methods[] = {
{ "nativeFinishInit", "()V",
(void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
......
};
//最后会调用到(*env)->RegisterNative()注册
return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
methods, NELEM(methods));
}
用上面的代码可知,nativeFinishInit函数映射了com_android_internal_os_RuntimeInit_nativeFinishInit函数,当java调用nativeFinishInit函数时,实际会调用到c/c++中的com_android_internal_os_RuntimeInit_nativeFinishInit函数。有读者可能会问,java调用jni函数时,虚拟机会自动映射,为什么要自己映射呢?如果jni函数比较少,这么做确实可行,但是我们可以看到gRegJNI数组是很庞大的,需要映射的函数也很多,如果全部交给虚拟机映射,会大大降低虚拟机的执行性能,所以我们提前注册JNI函数,虚拟机就可以直接找到对应的函数进行调用。
④: 通过反射调用ZygoteInit.java的main函数,正式进入java的世界。env->FindClass获取ZygoteInit类的类型,env->GetStaticMethodID获取函数main的函数id,env->CallStaticVoidMethod调用ZygoteInit.java的静态函数main。
ZygoteInit类的功能
至此,我们已经创建好了虚拟机,并且将ZygoteInit类装载到了虚拟机。接下来,ZygoteInit类将会被运行,那么ZygoteInit类具体有哪些功能呢?大致概括为如下几点:
绑定套接字,用来接收新Android应用程序运行请求
预加载Android Application Framework 使用的类与资源
启动并运行SystemServer
处理新Android应用程序运行请求
ZygoteInit的main函数:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
......
try{
boolean startSystemServer = false;
String socketName = "zygote";//套接字默认名称zygote
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
}
......
}
// ① 绑定/dev/socket/zygote套接字,用来接收Android应用程序运行请求
zygoteServer.registerServerSocketFromEnv(socketName);
......
if (!enableLazyPreload) {
......
// ② 预加载类与资源
preload(bootTimingsTraceLog);
......
}
......
if (startSystemServer) {
// ③ fork出system_server子进程
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// ③ {@code r == null}表示是父进程(zygote),{@code r != null}在子进程(system_server)
if (r != null) {
// ③ 如果是子进程(system_server)就执行run()方法,并返回,父进程(zygote)就继续往下执行
r.run();
return;
}
}
Log.i(TAG, "Accepting command socket connections");
// ④ 这轮询会在zygote进程中无限循环,而fork出的子进程(Android应用进程)会退出来
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
//system_server进程和android应用进程会关闭socket,zygote仍然在runSelectLoop中轮询监听socket
zygoteServer.closeServerSocket();
}
// ④ Android应用进程会走到这儿,执行相应的命令
if (caller != null) {
caller.run();
}
}
①: 绑定套接字,用来接收运行Android应用运行请求
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
void registerServerSocketFromEnv(String socketName) {
if (mServerSocket == null) {
int fileDesc;
//fullSocketName为“ANDROID_SOCKET_zygote”
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
//获取ANDROID_SOCKET_zygote的坏境变量(即为/dev/socket/zygote的文件描述符的值)
//是init进程在启动zygote进程时保存到环境变量中的
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
//绑定socket,在后面用来接收Android应用启动请求
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
mServerSocket = new LocalServerSocket(fd);
mCloseSocketFd = true;
} catch (IOException ex) {
......
}
}
}
②: 预加载类和资源,后面从zygote进程fork出的应用进程可以直接共享,加快应用进程启动速度。
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
static void preload(TimingsTraceLog bootTimingsTraceLog) {
......
preloadClasses();
......
preloadResources();
......
nativePreloadAppProcessHALs();
......
preloadOpenGL();
preloadSharedLibraries();
preloadTextResources();
.......
}
preloadClasses、preloadResources、nativePreloadAppProcessHALs预加载类和资源等等,有兴趣的同学可以深入了解。
③: forkSystemServer fork出system_server子进程,并返回可以调用SystemServer中main方法的Runnable r,并执行对应的run方法,而父进程zygote则继续往下执行runSelectLoop,监听Android应用运行执行请求。
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {
......
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000", //用户id
"--setgid=1000", //组id
......
"--nice-name=system_server",
......
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
......
//fork出system_server子进程,并且设置对应的参数
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.runtimeFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
//子进程(system_server)
if (pid == 0) {
......
//所以返回的r不为null,直接执行r.run
return handleSystemServerProcess(parsedArgs);
}
//父进程(zygote),返回的是null,继续往下执行
return null;
}
ZygoteInit的forkSystemServer方法会调用Zygote的forkSystemServer方法,如果是子进程(system_server)就返回handleSystemServerProcess(),父进程(zygote)就返回null。
frameworks/base/core/java/com/android/internal/os/Zygote.java
public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
......
int pid = nativeForkSystemServer(uid, gid, gids, runtimeFlags,
rlimits, permittedCapabilities, effectiveCapabilities);
......
return pid;
}
调用nativeForkSystemServer fork出子进程,nativeForkSystemServer是本地方法,在前面已经通过startReg方法中的register_com_android_internal_os_Zygote将nativeForkSystemServer方法映射到com_android_internal_os_Zygote_nativeForkSystemServer方法上,有兴趣的同学可以深入了解一下。
fork出子进程之后,子进程就开始调用handleSystemServerProcess()方法
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
......
//从环境变量SYSTEMSERVERCLASSPATH获取到SystemServer类文件相应jar包的路径
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
//对相应的jar包做dex优化处理
performSystemServerDexOpt(systemServerClasspath);
......
}
......
ClassLoader cl = null;
if (systemServerClasspath != null) {
//创建类加载器classloader
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
先从SYSTEMSERVERCLASSPATH环境中获取到SystemServer的classpath,然后使用performSystemServerDexOpt对classpath对应的jar包做dex优化处理。然后创建对应的classloader,后续用来加载SystemServer类,ZygoteInit.zygoteInit()继续往下执行:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
......
//将标准输出流和标准错误流重定向到Android log中
RuntimeInit.redirectLogStreams();
......
//本地方法,startReg映射,主要是开启ProcessState线程池,用来进行binder通信
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
redirectLogStreams会将标准输入,错误流重定位到Android log中,nativeZygoteInit JNI函数(startReg映射)会开启ProcessState线程池,用来进行binder通信。
继续往下执行RuntimeInit.applicationInit():
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,ClassLoader classLoader) {
......
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
继续往下执行:
没有翻译的英文注释也值得一看哦
/**
* Invokes a static "main(argv[]) method on class "className".
* Converts various failing exceptions into RuntimeExceptions, with
* the assumption that they will then cause the VM instance to exit.
*
* @param className Fully-qualified class name
* @param argv Argument vector for main()
* @param classLoader the classLoader to load {@className} with
*/
protected static Runnable findStaticMain(String className, String[] argv,ClassLoader classLoader) {
Class> cl;
......
//获取到SystemServer的类类型
cl = Class.forName(className, true, classLoader);
......
Method m;
try {
//获取到main方法的方法id
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
......
} catch (SecurityException ex) {
......
}
//这个就是③中forkSystemServer的返回值r
return new MethodAndArgsCaller(m, argv);
}
findStaicMain获取到SystemServer的类类型,并且获取到SystemServer中的main方法的方法id。然后new MethodAndArgsCaller(m,argv)就是③中forkSystemServer的返回值r,让我们看看r.run做了一些什么。
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
//通过反射调用mMethod静态方法
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
......
} catch (InvocationTargetException ex) {
......
}
}
}
由上可知,就是通过反射执行SystemServer类的main方法。众所周知,system_server进程注册和运行着AMS、PMS、PKMS等核心系统服务,因为这不是本文讲述的重点,所以有兴趣的同学可以继续深入了解一波~
④: zygoteServer.runSelectLoop()这轮询会在zygote进程中无限循环,而fork出的子进程(Android应用进程)会退出并继续往下执行
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
//开启zygote进程轮询监听。接收新的socket连接(会创建新的ZygoteConnection)
//并且从这些链接中中读取命令,并且执行
Runnable runSelectLoop(String abiList) {
ArrayList
ArrayList
fds.add(mServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
//开启轮询
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {//如果是新的socket链接请求(建立新连接)
//新建ZygoteConnection链接
ZygoteConnection newPeer = acceptCommandPeer(abiList);
//添加到链接数组中
peers.add(newPeer);
//添加到文件描述符数组中
fds.add(newPeer.getFileDesciptor());
} else {//如果是之前已经建立的socket链接(在已有连接上)
try {
//获取对应的ZygoteConnection
ZygoteConnection connection = peers.get(i);
//会执行ZygoteConnection发送过来的命令
final Runnable command = connection.processOneCommand(this);
if (mIsForkChild) {//子进程走这儿
......
//退出,command就是④中的caller
return command;
} else {//父进程走这儿,上面是while无限循环,zygote进程永远不会退出
......
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(i);
fds.remove(i);
}
}
} catch (Exception e) {
......
} finally {
mIsForkChild = false;
}
}
}
}
}
上面的流程概括来说,就是会轮询/dev/socket/zygote的socket,如果有新的链接,就新建ZygoteConnection,并将对应的socket fd添加到fds(轮询数组中),继续轮询,如果是新的链接,就重复上面的操作,如果是已经建立的链接,就执行该链接上读取到的command,也就是connection.processOneCommand()方法。
Android P之前processOneCommand的方法名是runOnce
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
//读取命令
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
......
}
......
parsedArgs = new Arguments(args);
......
//fork子进程
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
parsedArgs.instructionSet, parsedArgs.appDataDir);
try {
if (pid == 0) {
// 子进程中(应用进程中)
zygoteServer.setForkChild();
......
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.startChildZygote);
} else {
//父进程中(zygote)
......
return null;
}
} finally {
......
}
}
从当前链接socket中读取启动命令。如果读取成功,zygote将会fork出子进程,并且返回可以调用启动类的main方法的runnable(也就是④中的caller)
如果是AMS请求启动应用进程,启动类就是ActivityThread.java,caller.run()就会反射调用ActivityThread的main方法。
zygoteServer.setForkChild()将mIsForkChild全局变量设为true。
我们接下来分析handleChildProc()方法
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,FileDescriptor pipeFd, boolean isZygote) {
//关闭ZygoteConnection中的socket链接
closeSocket();
......
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
......
if (!isZygote) {
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,null /* classLoader */);
} else {
......
}
}
从ZygoteInit.zygoteInit()开始就和③中分析的代码一模一样了,这里就不重复分析了,③中返回的是可以调用SystemServer的main方法的Runnable,而④中返回的是可以调用ActivityThread的main方法的Runnable。
自此,ZygoteInit也已经分析完毕。
c++世界(app_main.cpp入口):
动态加载虚拟机动态库,启动java虚拟机
注册JNI本地函数,减轻虚拟机负担
装载ZygoteInit到java虚拟机,正式进入java世界
java世界(ZygoteInit.java入口):
绑定套接字,用来接收新Android应用程序运行请求
预加载Android资源,提高应用进程启动速度
启动并运行SystemServer(运行AMS、PMS等核心服务)
处理新Android应用程序运行请求
zygote进程启动其实没有特别难的难点,主要是繁琐,源码分析的过程是枯燥无味的,只有静下心来,才能有所收获。
本文忽略了很多细节,主要是介绍大致的流程,如果有错误的地方,还请大家批评指出~ 觉得写的不错也请点个赞~