深入理解Android 卷1:Zygote进入java

1.引言

上节记录到zygote进程的产生哪里,zygote是进入Java层的入口。下面就按照书上,博客上写的,结合源码看看是不是那么回事。最后会打印log看看究竟,个人认为只需要吧每个流程能在大脑中形成一个完整的回路就行,不必搞懂代码的具体实现。

2.app_main.cpp

Zygote相关的代码在app_main.cpp中,按照调用流程,结合源码看一遍是不是那么回事。

app_main.cpp中 int main()方法有一段代码很重要,这段代码就能进入java层。


深入理解Android 卷1:Zygote进入java_第1张图片
image.png

AppRuntime 继承AndroidRuntime

深入理解Android 卷1:Zygote进入java_第2张图片
image.png

AppRuntime的调用:


深入理解Android 卷1:Zygote进入java_第3张图片
image.png

深入理解Android 卷1:Zygote进入java_第4张图片
image.png

start方法做了三件事:
1.初始化虚拟机,为进入java层做准备
2.注册jni函数。这句话可能不理解。这么说吧,Android系统本身有很多地方都是采用了jni。最常见
env->FindClass .没有这步注册动作,就没得这个api
3.通过反射调用ZygoteInit.java

初始化jvm

深入理解Android 卷1:Zygote进入java_第5张图片
image.png

注册jni函数

深入理解Android 卷1:Zygote进入java_第6张图片
image.png

反射调用java代码,进入java世界

深入理解Android 卷1:Zygote进入java_第7张图片
image.png

从代码片段可以看出调用的事main方法,且该方法还是一个静态的。进入ZygoteInit看看是否有这个方法。


深入理解Android 卷1:Zygote进入java_第8张图片
image.png

看到main()方法的确是有的并且还是一个static。

3.ZygoteInit.java

这个java层入口。按照书上说的,下面标注的是很重要的5个步骤。


深入理解Android 卷1:Zygote进入java_第9张图片
image.png

3.1 registerZygoteSocket

深入理解Android 卷1:Zygote进入java_第10张图片
image.png

registerZygoteSocket函数,这个函数其实很简单,就是创建了一个服务端的socket,并赋值给全局变量sServerSocket。那么这个服务端的socket具体要接受什么消息?当请求新建一个进程的时候,就会被这个socket接收到请求,然后就被处理。

3.2 preload()

深入理解Android 卷1:Zygote进入java_第11张图片
image.png

3.3 gcAndFinalize()

深入理解Android 卷1:Zygote进入java_第12张图片
image.png

3.4 startSystemServer

系统初始化到这里之后,系统中已经有3个进程了,最开始的init,zygote和zygote分裂出来的system_server。system_server部门我们以后再看,接着看zygote的执行。

深入理解Android 卷1:Zygote进入java_第13张图片

3.5 runSelectLoop

runSelectLoop函数的逻辑比较简单,主要有两点:
1、 处理客户端的连接和请求。其中客户端在zygote进程中使用ZygoteConnection对象表示。
2、 客户的请求有ZygoteConnection的runOnce来处理。


深入理解Android 卷1:Zygote进入java_第14张图片
image.png

4 SystemServer进程的作用

看如下代码:
startSystemServer()中有一个handlerSystemServerProcess()方法。顾名思义处理系统Server过程的方法。ActivityManagerService,WindowManagerService这些服务都是SystemServer进程处理的

handlerSystemServerProcess

深入理解Android 卷1:Zygote进入java_第15张图片
image.png

RuntimeInit.zygoteInit()通过抛出异常

深入理解Android 卷1:Zygote进入java_第16张图片
image.png

nativeZygoteInit()最后调用的是:

深入理解Android 卷1:Zygote进入java_第17张图片
image.png

applicationInit里面有一个invokeStaticMain方法,该方法通过传入的className,反射得到Method,然后抛出异常,其中参数m 就是className的Main方法,并且异常被ZygoteInit.main的catch捕捉到(实际上是android.app.ActivityThread类的main函数)。

深入理解Android 卷1:Zygote进入java_第18张图片

ZygoteInit捕捉异常:

深入理解Android 卷1:Zygote进入java_第19张图片
image.png

caller.run()通过这种方式间接性的调用了,SystemServer的main函数。

深入理解Android 卷1:Zygote进入java_第20张图片

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

你可能感兴趣的:(深入理解Android 卷1:Zygote进入java)