Zygote的父进程是init进程,他孵化了SystemServer进程,以及咱们的运用进程。
一、Zygote作用
功能首要是
:发动安卓虚拟机DVM
:发动SystemServer(Android体系进程)
:孵化运用进程
:加载 常用类 JNI函数 主题资源 共享库 等
Zygote进程和体系其他进程的关系如图所示:
二、Zygote进程发动和运用进程发动
如图所示:
1.Zygote进程发动流程
Zygote是由init进程发动的,init进程是Linux体系发动后用户空间的第一个进程, 首要会去加载init.rc配置文件,然后发动其间界说的体系服务(Zygote,ServiceManager等), Init进程创立Zygote时,会调用app_main.cpp的main() 办法, 发动Zygote后,发动安卓虚拟机,接着在native层中经过jni调用java层的ZygoteInit的main()。
<!--app_main.cpp
int main(int argc, char* const argv[])
{
// 创立Android运行时目标
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// 代码省略...
// 调用AppRuntime.start办法,
// 而AppRuntime是AndroidRuntime的子类,并且没有重写start办法
// 因此调用的是AndroidRuntime的start办法
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}
-->
这里总共就做了两件事,第一件创立AppRuntime,第二件调用start办法,具体看一下start办法:
<!--
/*
* AndroidRuntime.cpp
* Start the Android runtime.
*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
/* start the virtual machine */
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
-->
startVM — 发动Java虚拟机
startReg — 注册JNI 经过JNI调用Java办法,履行com.android.internal.os.ZygoteInit 的 main 办法。
ZygoteInit .main首要干了4个事情,如下:
<!--
/*frameworks/base/core/java/com/android/internal/os/ZygoteInit.java*/
public static void main(String[] argv) {
ZygoteServer zygoteServer = null;
...
try {
...
// 1.preload提前加载框架通用类和体系资源到进程,加快进程发动
preload(bootTimingsTraceLog);
...
// 2.创立zygote进程的socket server服务端目标
zygoteServer = new ZygoteServer(isPrimaryZygote);
...
// 3.发动SystemServer(Android体系进程)
forkSystemServer
...
// 4.进入死循环,等候AMS发恳求过来
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
...
} finally {
...
}
...
caller.run();//履行MethodAndArgsCaller包装后的runnable
}
-->
1.创立了ZygoteServer:这是一个Socket相关的服务,目的是进行跨进程通信。
2.预加载preload:预加载相关的资源。
3.创立SystemServer进程: 经过forkSystemServer割裂出了两个进程,一个Zygote进程,一个SystemServer进程。而且由于是割裂的, 所以新割裂出来的进程也具有虚拟机,也能调用JNI,也具有预加载的资源,也会履行后续的代码。
4.履行runSelectLoop():内部是一个while(true)循环,等候AMS创立新的进程的請求音讯。(想想Looper.loop())
2.Zygote发动运用进程流程
zygote进程经过Socket监听接纳AMS的恳求,fork创立子运用进程,然后pid为0时进入子进程空间,然后在ZygoteInit#zygoteInit中完结进程的初始化动作。
先看一下ZygoteServer.runSelectLoop
<!--
/*frameworks/base/core/java/com/android/internal/os/ZygoteServer.java*/
Runnable runSelectLoop(String abiList) {
// 进入死循环监听
while (true) {
while (--pollIndex >= 0) {
if (pollIndex == 0) {
...
} else if (pollIndex < usapPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket
// 得到一个恳求连接封装目标ZygoteConnection
ZygoteConnection connection = peers.get(pollIndex);
// processCommand函数中处理AMS客户端恳求
final Runnable command = connection.processCommand(this, multipleForksOK);
...
}
}
}
}
-->
再通過ZygoteConnection中处理AMS创立新运用进程的恳求。
<!--
//ZygoteConnection.java
Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
...
// 1.fork创立运用子进程
pid = Zygote.forkAndSpecialize(...);
try {
if (pid == 0) {
...
// 2.pid为0,当时处于新创立的子运用进程中,处理恳求参数
return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);
} else {
...
handleParentProc(pid, serverPipeFd);
}
} finally {
...
}
}
private Runnable handleChildProc(ZygoteArguments parsedArgs,
FileDescriptor pipeFd, boolean isZygote) {
...
// 关闭从父进程zygote承继过来的ZygoteServer服务端地址
closeSocket();
...
if (parsedArgs.mInvokeWith != null) {
...
} else {
if (!isZygote) {
// 持续进入ZygoteInit#zygoteInit持续完结子运用进程的相关初始化工作
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
...
}
}
}
-->
经过调用Zygote.forkAndSpecialize()函数来创立子进程,会有一个回来值pid,分别在子进程和父进程各回来一次, 子进程回来 0 ,父进程回来1,经过判别pid为0仍是1来判别当时是是父进程仍是子进程;默许子进程承继父进程是承继了父进程的一切资源 分叉后的进程会将socket停掉并重新初始化一些数据,但preload的资源和类保和VM留了下来,运用进程承继了Zygote进程所创立的虚拟机, 运用进程的在运用的时分就不需要再去创立,自此新的进程和zygote进程分道扬镳。
留意:其间包含运用进程的主线程也是在这里从zygote进程承继而来的,运用进程的主线程并不是自己自动创立的新线程。
Zygote发动运用进程的时分不管父进程中有多少个线程,子进程在创立的时分都只有一个线程,对于子进程来说,多出现的线程在子进程中都不复存在, 因为如果其他线程也被复制到子进程,这时在子进程中就会存在一些问题,有时程序在履行的过程中可能会形成死锁,状态不一致等,所以比较安全的做法是在创立子进程的时分,只保存父进程的 主线程,其他都在暂停(此时线程资源是开释的所以不会承继到子进程),子进程发动完后再重启这些线程。
ZygoteInit.zygoteInit办法完结运用进程初始化:
<!--
/*frameworks/base/core/java/com/android/internal/os/ZygoteInit.java*/
public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
...
// 原生增加名为“ZygoteInit ”的systrace tag以标识进程初始化流程
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
// 1.RuntimeInit#commonInit中设置运用进程默许的java反常处理机制
RuntimeInit.commonInit();
// 2.ZygoteInit#nativeZygoteInit函数中JNI调用发动进程的binder线程池
ZygoteInit.nativeZygoteInit();
// 3.RuntimeInit#applicationInit中反射创立ActivityThread目标并调用其“main”进口办法
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}
-->
1.设置运用进程默许的java反常处理机制(可以实现监听、拦截运用进程所有的Java crash的逻辑);
2.JNI调用发动进程的binder线程池(留意运用进程的binder线程池资源是自己创立的并非从zygote父进程承继的);
3.经过反射创立ActivityThread目标并调用其“main”进口办法。
最后再看看RuntimeInit.applicationInit做了啥:
<!--
/*frameworks/base/core/java/com/android/internal/os/RuntimeInit.java*/
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
...
// 结束“ZygoteInit ”的systrace tag
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
// 1.反射加载创立ActivityThread类目标
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
...
}
Method m;
try {
// 2.反射调用其main办法
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
...
} catch (SecurityException ex) {
...
}
...
// 3.触发履行以上逻辑
return new MethodAndArgsCaller(m, argv);
}
-->
首要就是调用ActivityThread.main办法,从此进入ActivityThread中。
三、参考资料
【Zygote进程的发动 –学习笔记】 blog.csdn.net/qq\_4223721…
【说说你对zygote的了解?】www.cnblogs.com/rxh1050/p/1…
【Zygote Fork机制与资源预加载】www.jianshu.com/p/be384613c…