上面的函数中,调用了AppRuntime中的start方法,AppRuntime继承AndroidRuntime,调用的start也是AndroidRuntime里的方法。
AndroidRuntime.cpp
①//创建虚拟机
if (startVm(&mJavaVM, &env) != 0) goto bail; ②注册JNI函数if (startReg(env) <0) {LOGE("Unable to register all android natives\n");goto bail;
}③ 通过JNI调用ZygoteInit下的main函数 进入Java世界
env->CallStaticVoidMethod(startClass, startMeth, strArray);
1 创建虚拟机
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)//大部分是设置虚拟机参数
{
//设置JNI check选项的 检查资源是否被正确释放 字符集的要求等 缺点:耗时
property_get("dalvik.vm.checkjni", propBuf, "");//设置虚拟机的heapsize 默认是16MB 太小会导致操作大图片的时候无法分配内存strcpy(heapsizeOptsBuf, "-Xmx");property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
}
2 注册JNI函数
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{ //设置Thread类的线程创建函数是javaCreateThreadEtcandroidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);env->PushLocalFrame(200);// 注册JNI函数 gRegJNI是一个全局数组
/*register_jni_procs函数里调用数组的Proc方法,Proc方法是为了注册JNI函数,数组是gRegJNI包含了所需要注册的JNI函数*/if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) <0) {env->PopLocalFrame(NULL);return -1;}env->PopLocalFrame(NULL);//createJavaThread("fubar", quickTest, (void*) "hello");return 0;
}
![](https://img2.php1.cn/3cdc5/3e52/5a0/3f2f63fa4b31ef56.png)
接下来就进入了Java世界,Java世界的入口---frameworks/base/core/java/com/android/internal/os ZygoteInit.java
public static void main(String argv[]) {
try{
registerZygoteSocket(); //① 注册zygote用到的socketpreloadClasses(); //②预加载类和资源
preloadResources();if (argv[1].equals("true")) {startSystemServer(); //③启动SystemServer}if (ZYGOTE_FORK_MODE) {runForkMode(); //④
} else {runSelectLoopMode();}
}catch(MethodAndArgsCaller caller){
caller.run(); //⑤
}
}
- 建立IPC通信服务端registerZygoteSocket
IPC---InterProcess Communication 进程间通信,指的是在不同进程之间传播交换信息,不同进程之间用户空间独立,共享内存区是公用的,常见的IPC通信有:管道、消息队列、 信号量、共享内存、socket、Streams等
private static void registerZygoteSocket() {if (sServerSocket == null) {int fileDesc;try { //从环境变量获取socket的fd(启动时传入)String env = System.getenv(ANDROID_SOCKET_ENV);fileDesc = Integer.parseInt(env);} ......try { //创建服务端socketsServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));}......}}
- 预加载类和资源
private static void preloadClasses() {//预加载的类信息存储在PRELOADED_CLASSES里InputStream is = ZygoteInit.class.getClassLoader().getResourceAsStream(
if (is == null) {Log.e(TAG, "Couldn&#39;t find " + PRELOADED_CLASSES + ".");} else { //准备工作 }
//读取文件的每一行while ((line = br.readLine()) != null) {// Skip comments and blank lines.line = line.trim();if (line.startsWith("#") || line.equals("")) {continue;}//通过Java反射来加载类 line中存储的是预加载的类名Class.forName(line);
}
在/AOSP/frameworks/base/preloaded-classes下是要加载的所有类,数量很多高达1200+行
![](https://img2.php1.cn/3cdc5/3e52/5a0/b74042af61805f96.png)
Preload_class文件由framework/base/tool/preload工具生成,他要判断每个类加载的时间是否大于1250us,超过这个时间写入到preload_classes文件中,由zygote预加载。由于要加载的类十分多,这也导致了android启动时间很长。
③启动system_server
StartSystemServer会创建Java世界中系统Service所驻留的进程,该进程是framework核心,他如果死了,zygote就会自杀。zygote压力大,分裂了一个子进程为他做一些事情。
private static boolean startSystemServer()throws MethodAndArgsCaller, RuntimeException {
//设置参数String args[] = {"--setuid=1000","--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003","--capabilities=130104352,130104352","--runtime-init","--nice-name=system_server",//进程名"com.android.server.SystemServer",};ZygoteConnection.Arguments parsedArgs = null;int pid;try {parsedArgs = new ZygoteConnection.Arguments(args);int debugFlags = parsedArgs.debugFlags;if ("1".equals(SystemProperties.get("ro.debuggable")))debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;/* zygote分裂了一个子进程 */pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,parsedArgs.gids, debugFlags, null,parsedArgs.permittedCapabilities,parsedArgs.effectiveCapabilities);} catch (IllegalArgumentException ex) {throw new RuntimeException(ex);}if (pid == 0) {//pid=0表明处于子进程中,开始执行system_server的工作handleSystemServerProcess(parsedArgs);}return true;}
④ runSelectLoopMode
当函数分裂了system_server进程后进入到了下一个关键函数runSelectLoopMode,这里将会使用到前面第一步创建的socket
private static void runSelectLoopMode() throws MethodAndArgsCaller {ArrayList fds = new ArrayList();ArrayList peers = new ArrayList();FileDescriptor[] fdArray = new FileDescriptor[4];
//第一步创建的服务端socketfds.add(sServerSocket.getFileDescriptor());peers.add(null);
while (true) {int index=0;try {
//selectReadable内部调用select,使用多路复用IO模型,有客户端连接//或者有数据时//selectReadable就会返回fdArray = fds.toArray(fdArray);index = selectReadable(fdArray);} catch (IOException ex) {throw new RuntimeException("Error in select()", ex);}
//客户端代表的是ZygoteConnection,
else if (index == 0) {ZygoteConnection newPeer = acceptCommandPeer();peers.add(newPeer);fds.add(newPeer.getFileDesciptor());} else {boolean done;
// peers.get(index)返回的是ZygoteConnection,然后调用runOnce函数完成dOne= peers.get(index).runOnce();
}
总结:主要是处理客户连接和客户请求,客户在zygote中用ZygoteConnection 表示,客户的请求由runOnce函数完成。
至此Zygote便睡去了,默默守护在我们周围。当收到子孙后代的请求后,会被随时叫醒。
下一章节,将来学习Zygote的子进程SystemServer