1.引言
上节记录到zygote进程的产生哪里,zygote是进入Java层的入口。下面就按照书上,博客上写的,结合源码看看是不是那么回事。最后会打印log看看究竟,个人认为只需要吧每个流程能在大脑中形成一个完整的回路就行,不必搞懂代码的具体实现。
2.app_main.cpp
Zygote相关的代码在app_main.cpp中,按照调用流程,结合源码看一遍是不是那么回事。
app_main.cpp中 int main()方法有一段代码很重要,这段代码就能进入java层。
AppRuntime 继承AndroidRuntime
AppRuntime的调用:
start方法做了三件事:
1.初始化虚拟机,为进入java层做准备
2.注册jni函数。这句话可能不理解。这么说吧,Android系统本身有很多地方都是采用了jni。最常见
env->FindClass .没有这步注册动作,就没得这个api
3.通过反射调用ZygoteInit.java
初始化jvm
注册jni函数
反射调用java代码,进入java世界
从代码片段可以看出调用的事main方法,且该方法还是一个静态的。进入ZygoteInit看看是否有这个方法。
看到main()方法的确是有的并且还是一个static。
3.ZygoteInit.java
这个java层入口。按照书上说的,下面标注的是很重要的5个步骤。
3.1 registerZygoteSocket
registerZygoteSocket函数,这个函数其实很简单,就是创建了一个服务端的socket,并赋值给全局变量sServerSocket。那么这个服务端的socket具体要接受什么消息?当请求新建一个进程的时候,就会被这个socket接收到请求,然后就被处理。
3.2 preload()
3.3 gcAndFinalize()
3.4 startSystemServer
系统初始化到这里之后,系统中已经有3个进程了,最开始的init,zygote和zygote分裂出来的system_server。system_server部门我们以后再看,接着看zygote的执行。
3.5 runSelectLoop
runSelectLoop函数的逻辑比较简单,主要有两点:
1、 处理客户端的连接和请求。其中客户端在zygote进程中使用ZygoteConnection对象表示。
2、 客户的请求有ZygoteConnection的runOnce来处理。
4 SystemServer进程的作用
看如下代码:
startSystemServer()中有一个handlerSystemServerProcess()方法。顾名思义处理系统Server过程的方法。ActivityManagerService,WindowManagerService这些服务都是SystemServer进程处理的
handlerSystemServerProcess
RuntimeInit.zygoteInit()通过抛出异常
nativeZygoteInit()最后调用的是:
applicationInit里面有一个invokeStaticMain方法,该方法通过传入的className,反射得到Method,然后抛出异常,其中参数m 就是className的Main方法,并且异常被ZygoteInit.main的catch捕捉到(实际上是android.app.ActivityThread类的main函数)。
ZygoteInit捕捉异常:
caller.run()通过这种方式间接性的调用了,SystemServer的main函数。
5. 应用打开过程
打开一个应用相当于是开启了一个进程,这个流程是怎样执行的呢?
解析:
ActivityManagerService将请求发送给zygote进程后, 就轮到zygote进程处理消息了。通过分析zygote进程的启动流程,我们已经知道zygote进程收到请求后,将执行ZygoteConnection的runOnce函数。
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList fds = new ArrayList();
ArrayList peers = new ArrayList();
......
for (int i = pollFds.length - 1; i >= 0; --i) {
.........
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
//处理请求
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
............
}
接下来,我们看看函数runOnce的实际操作
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
//解析传入的参数
........
try {
.......
//与启动SystemServer进程一样,最终也会通过native函数fork,并配置进程的参数
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet, parsedArgs.appDataDir);
} catch (ErrnoException ex) {
.......
} catch (IllegalArgumentException ex) {
.......
} catch (ZygoteSecurityException ex) {
.......
}
try {
if (pid == 0) {
// 子进程创建成功
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//子进程根据参数利用handleChildProc作进一步处理
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// should never get here, the child is expected to either
// throw ZygoteInit.MethodAndArgsCaller or exec().
return true;
} else {
// in parent...pid of < 0 means failure 创建失败
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
//父进程进行一些后续操作,例如清理工作等
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
最后,我们看看handlehandleChildProc:
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller {
//关闭fork过来的zygote server socket
closeSocket();
ZygoteInit.closeServerSocket();
//处理参数
........
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(.....)
} else {
//完成进程的初始化,然后抛异常
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */);
}
}
从上面的代码可以看出,函数handleChildProc最终还是会调用Runtime的zygoteInit。
如同SystemServer进程一样,普通进程也会进行一些初始化,建立binder通信后,抛出异常,最终由ZygoteInit.java捕获异常,然后反射启动对应类的main函数(实际上是android.app.ActivityThread类的main函数)。
参考连接:
http://blog.csdn.net/gaugamela/article/details/52261075
http://blog.csdn.net/hu3167343/article/details/38370993
https://www.cnblogs.com/bastard/archive/2012/09/03/2668579.html