zygote本身是一个Native应用程序,在Android.mk中指定的名字是app_process,源码位置:
framework/base/cmds/app_process/App_main.cpp
该代码重要功能是由AppRuntime的start完成的,而这个函数使用的是基类AndroidRuntime的start,分析AndroidRuntime:
1、创建虚拟机,调用Jni创建。JNI_CreateJavaVM
2、给虚拟机注册JNI函数,startReg
在zygoteinit.java中进入java世界,不再返回Native,
1、建立IPC通信服务端-registerZygoteSocket,创建一个服务端的socket
2、preloadClass和preloadresources,预加载类和资源,这里预加载类有很多,加载preloaded-classes文件的内容,是导致android系统启动慢的原因之一。preloadResources主要加载framework-res.apk中的资源
3、启动system_server,创建了一个子进程处理java
4、runSelectLoopMode,这里补充下socket的知识,socket中有两种方式触发读数据,第一种:使用listen()去监听某个端口,再read从该端口读数据,这种方式称为阻塞式读操作,因为当端口没有数据时,read函数将一直等待,直到有数据才返回;第二种:使用select函数将需要监听的文件描述符作为select函数的参数,当文件描述符中出现新的数据,自动触发一个中断,然后在中断处理中去读制定文件描述符的数据,这种方式为非阻塞式操作。而这里使用的是第二种。而客户端用ZygoteConnection来表示,在runOnce中处理。
对SystemServer进行分析:
通过Zygote.forkSystemServer函数fork出一个新的进程,setSignalHandler设置信号处理函数,使子进程SystemServer和Zygote一同开启,一同结束。创建完进程后,执行handleSystemServerProcess,与Binder通信建立联系。然后调用systemserver的main函数。fork的返回值大于0时,代表父进程,返回值等于0时,代表复制的子进程。调用invokeStaticMain函数抛出异常,在ZygoteInit的main中捕获,调用systemserver的main函数。
总结:Zygote fork出进程SystemServer主要是为了调用main函数,加载libandroid_server.so 库,init1是native函数,将调用线程加入Bindle通信中,init2单独创建一个线程,启动系统的各项服务
以一个Activity的启动为例,zygote是怎么处理的:
ActivityManagerService是由SystemServer创建的,假如通过startActivity启动一个新的Activity,会先调用ActivityManagerService的startProcessLocked,最终调用zygoteSendArgsAndGeiPid打开和zygote通信的socket,并向该socket发送数据请求,此时,ZygoteInit中runSelectLoopMode正在用非阻塞的方式等待数据,有数据来时,调用runOnce处理,在runOnce中fork出一个新的进程,然后调用invokeStaticMain函数抛出异常,调用systemserver的main函数继续等待请求下一次分裂。
注意:
创建虚拟机时,heapsize的限制,一般为最大值16MB或者32MB
开机速度优化:
1、ZygoteInit中加载了preloadclasses有1000多个类,耗费时间太多;
2、preloadresources对所有apk文件进行加载;
3、SystemServer创建的Service有很多,像AMS等等。
wait和notify:
synchronized(obj) { while(!condition) { obj.wait(); } obj.doSomething(); }
当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。当另一线程获取到obj锁后,改变条件,可以唤醒A
synchronized(obj) { condition = true; obj.notify(); }