本文中的native层源码为1.6版本
文章目录
1 Zygote简介
虚拟机启动耗时
- Zygote进程运行时,会初始化Dalvik虚拟机,并启动它。
- Android的应用程序是由java编写的,不能直接以本地进程的形态运行在Linux上,只能运行在Dalvik虚拟机中。并且每个应用程序都运行在各自的虚拟机中,引用程序每次运行都要重新初始化并启动虚拟机
- 应用程序每次运行都要重新初始化并启动虚拟机,这个过程会耗费相当长时间,是拖慢应用程序的原因之一
使用Zygote的目的
- 嵌入式设备拥有的资源非常有限,需要内嵌系统平台提供一个高效的运行环境,来提高设备资源的利用率和使用时间
- Zygote进程再“孵化”新进程时,能有效的减少系统负担,提高进程“孵化”速度
启动过程
- init进程是系统启动后运行在用户空间的首个进程
- init进程启动完系统运行所需的各种Daemon后,启动Zygote进程
- Zygote进程启动后,Android的服务与应用程序都由Zygote进程启动运行
Linux系统与Android系统创建进程的区别
- Zygote通过COW(Copy On Write)方式对运行在内存中的进程实现了最大程度的复用,并通过库共享有效地降低了内存的使用量
2 由app_process运行ZygoteInit class
与其他本地服务或Daemon不同的是,Zygote由Java编写,不能直接由init进程启动运行,若想运行Zygote类,必须先生成Dalvik虚拟机,再在Dalvik虚拟机上运行ZygoteInit类,执行这一任务的就是app_process进程
2.1 创建AppRuntime对象
此函数位置: /frameworks/base/cmds/app_process/app_main.cpp
118int main(int argc, const char* const argv[])
119{
130 AppRuntime runtime; //1 创建AppRuntime对象,其父类用于启动和运行虚拟机
131 const char *arg;
132 const char *argv0;
143 int i = runtime.addVmArguments(argc, argv);
145 // Next arg is parent directory
146 if (i < argc) {
147 runtime.mParentDir = argv[i++];
148 }
180}
- AppRuntime继承自AndroidRunTime,AndroidRuntime用于初始化并与运行Dalvik虚拟机,为运行Andriod应用程序做好准备
- 在运行Dalvik虚拟机之前,通过Runtime对象,分析环境变量以及运行的参数,并以此作为虚拟机选项
2.2 调用AppRuntime对象
118int main(int argc, const char* const argv[])
119{
151 if (i < argc) {
152 arg = argv[i++];
153 if (0 == strcmp("--zygote", arg)) { //2 判断arg参数是否为“--zygote”
154 bool startSystemServer = (i < argc) ?
155 strcmp(argv[i], "--start-system-server") == 0 : false;
156 setArgv0(argv0, "zygote");
157 set_process_name("zygote");
158 runtime.start("com.android.internal.os.ZygoteInit", //3 启动虚拟机,并将ZygoteInit类加载到内存中
159 startSystemServer);
160 } else {
...
172 }
173 }
180}
2.3 创建Dalvik虚拟机
512void AndroidRuntime::start(const char* className, const bool startSystemServer)
544 property_get("dalvik.vm.checkjni", propBuf, ""); // 1 调用property_get()函数来访问系统中设置的相关值
545 if (strcmp(propBuf, "true") == 0) {
546 checkJni = true;
547 } else if (strcmp(propBuf, "false") != 0) {
548 /* property is neither true nor false; fall back on kernel parameter */
549 property_get("ro.kernel.android.checkjni", propBuf, "");
550 if (propBuf[0] == '1') {
551 checkJni = true;
552 }
553 }
774 if (JNI_CreateJavaVM(&mJavaVM, &env, &initArgs) < 0) { //2 创建并运行虚拟机
775 LOGE("JNI_CreateJavaVM failed\n");
776 goto bail;
777 }
782 if (startReg(env) < 0) { //3 注册本地函数
783 LOGE("Unable to register all android natives\n");
784 goto bail;
785 }
849}
JNI_CreateJavaVM函数原型
3501 jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) function
JavaVM** p_vm: 生成的JavaVM类的接口指针
JNIEnv** p_env:JNIEnv类的接口指针,方便访问虚拟机
void* vm_args:已设置的虚拟机选项
2.4 运行ZygoteInit类
创建完VM之后,接着加载要运行的类
512void AndroidRuntime::start(const char* className, const bool startSystemServer)
815 slashClassName = strdup(className);
816 for (cp = slashClassName; *cp != '\0'; cp++)
817 if (*cp == '.')
818 *cp = '/';//1 将 "." 替换成 “/”
819
820 startClass = env->FindClass(slashClassName);//2 在指定路径下查找类名
821 if (startClass == NULL) {
822 LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
823 /* keep going */
824 } else {
825 startMeth = env->GetStaticMethodID(startClass, "main", //3 获取指定类下的方法
826 "([Ljava/lang/String;)V");
827 if (startMeth == NULL) {
828 LOGE("JavaVM unable to find main() in '%s'\n", className);
829 /* keep going */
830 } else {
831 env->CallStaticVoidMethod(startClass, startMeth, strArray);//4 此时程序的执行会转到虚拟机中运行的java程序上
832
833#if 0
834 if (env->ExceptionCheck())
835 threadExitUncaughtException(env);
836#endif
837 }
838 }
3 ZygoteInit类的功能
516 public static void main(String argv[]) {
517 try {
518 registerZygoteSocket(); //1 绑定套接字,接收新Android应用程序运行请求
519 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
520 SystemClock.uptimeMillis());
521 preloadClasses(); //2 加载Android Application Framework
522 preloadResources();
523 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
524 SystemClock.uptimeMillis());
525
526 // Do an initial gc to clean up after startup
527 gc();
528
529 // If requested, start system server directly from Zygote
530 if (argv.length != 2) {
531 throw new RuntimeException(
532 "ZygoteInit.main expects two arguments");
533 }
534
535 if (argv[1].equals("true")) {
536 startSystemServer();//3 运行SystemServer
537 }
538
539 Log.i(TAG, "Accepting command socket connections");
540
541 if (ZYGOTE_FORK_MODE) {
542 runForkMode();//4 处理新Android应用程序运行请求
543 } else {
544 runSelectLoopMode();
545 }
546
547 closeServerSocket();
548 } catch (MethodAndArgsCaller caller) {
549 caller.run();
550 } catch (RuntimeException ex) {
551 Log.e(TAG, "Zygote died with exception", ex);
552 closeServerSocket();
553 throw ex;
554 }
555 }
3.1 绑定/dev/socket/zygote套接字
绑定套接字的目的是为了接收应用程序创建的请求
69 private static LocalServerSocket sServerSocket;
150 private static void registerZygoteSocket() {
151 if (sServerSocket == null) {
152 int fileDesc;
153 try {
154 String env = System.getenv(ANDROID_SOCKET_ENV);
155 fileDesc = Integer.parseInt(env);
156 } catch (RuntimeException ex) {
157 throw new RuntimeException(
158 ANDROID_SOCKET_ENV + " unset or invalid", ex);
159 }
160
161 try {
162 sServerSocket = new LocalServerSocket( //1 创建LocalServerSocket对象并赋值给
163 createFileDescriptor(fileDesc)); //2 获取套接字的文件描述符
164 } catch (IOException ex) {
165 throw new RuntimeException(
166 "Error binding to local socket '" + fileDesc + "'", ex);
167 }
168 }
169 }
3.2 加载应用程序Framework中类与平台资源
92 private static final String PRELOADED_CLASSES = "preloaded-classes";
233 private static void preloadClasses() {
234 final VMRuntime runtime = VMRuntime.getRuntime();
235
236 InputStream is = ZygoteInit.class.getClassLoader().getResourceAsStream(
237 PRELOADED_CLASSES); //1 获取输入流,用于读取“preloaded-classes”文件中的类
259 BufferedReader br
260 = new BufferedReader(new InputStreamReader(is), 256);//2 创建BufferedReader,用于读取文件内容
276 Class.forName(line); //3 动态加载类
328 }
337 private static void preloadResources() {
338 final VMRuntime runtime = VMRuntime.getRuntime();
339
340 Debug.startAllocCounting();
341 try {
342 runtime.gcSoftReferences();
343 runtime.runFinalizationSync();
344 mResources = Resources.getSystem(); //1 获取系统资源加载对象
345 mResources.startPreloading(); //2 开始预加载
346 if (PRELOAD_RESOURCES) {
350 TypedArray ar = mResources.obtainTypedArray( //3 加载drawable资源
351 com.android.internal.R.array.preloaded_drawables);
352 int N = preloadDrawables(runtime, ar);
357 ar = mResources.obtainTypedArray(//4 加载colorlist资源
358 com.android.internal.R.array.preloaded_color_state_lists);
359 N = preloadColorStateLists(runtime, ar);
362 }
369 }
370
3.3 运行SystemServer
472 private static boolean startSystemServer()
473 throws MethodAndArgsCaller, RuntimeException {
474 /* Hardcoded command line to start the system server */
475 String args[] = { //1 硬编码来保存SystemServer启动的参数,"com.android.server.SystemServer"用于指定System类
476 "--setuid=1000",
477 "--setgid=1000",
478 "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
479 "--capabilities=130104352,130104352",
480 "--runtime-init",
481 "--nice-name=system_server",
482 "com.android.server.SystemServer",
483 };
...
500 /* Request to fork the system server process */
501 pid = Zygote.forkSystemServer( //2 创建新进程并运行SystemServer
502 parsedArgs.uid, parsedArgs.gid,
503 parsedArgs.gids, debugFlags, null);
...
507
508 /* For child process */
509 if (pid == 0) {
510 handleSystemServerProcess(parsedArgs); //3 在生成的进程中调用com.android.server.SystemServer类中的main()方法
511 }
512
513 return true;
514 }
SystemServer#main()
428 public static void main(String[] args) {
429 // The system server has to run all of the time, so it needs to be
430 // as efficient as possible with its memory usage.
431 VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
432
433 System.loadLibrary("android_servers");
434 init1(args);//init1是native函数,将会调用system_init.cpp中声明的jni函数
435 }
将会调用以下jni函数
/frameworks/base/cmds/system_server/library/system_init.cpp
26static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz)
27{
28 system_init();
29}
30
/frameworks/base/cmds/system_server/library/system_init.cpp#system_init()
52extern "C" status_t system_init()
53{
54 LOGI("Entered system_init()");
55
56 sp<ProcessState> proc(ProcessState::self());
57
58 sp<IServiceManager> sm = defaultServiceManager();
59 LOGI("ServiceManager: %p\n", sm.get());
60
61 sp<GrimReaper> grim = new GrimReaper();
62 sm->asBinder()->linkToDeath(grim, grim.get(), 0);
63
64 char propBuf[PROPERTY_VALUE_MAX];
65 property_get("system_init.startsurfaceflinger", propBuf, "1");
66 if (strcmp(propBuf, "1") == 0) {
67 // Start the SurfaceFlinger
68 SurfaceFlinger::instantiate();//1 初始化SurfaceFlinger服务
69 }
70
71 // On the simulator, audioflinger et al don't get started the
72 // same way as on the device, and we need to start them here
73 if (!proc->supportsProcesses()) {
74
75 // Start the AudioFlinger
76 AudioFlinger::instantiate();//2 初始化AudioFlinger服务
77
78 // Start the media playback service
79 MediaPlayerService::instantiate();//3 初始化MediaPlayerService服务
80
81 // Start the camera service
82 CameraService::instantiate();//4 初始化CameraService服务
83 }
84
85 // And now start the Android runtime. We have to do this bit
86 // of nastiness because the Android runtime initialization requires
87 // some of the core system services to already be started.
88 // All other servers should just start the Android runtime at
89 // the beginning of their processes's main(), before calling
90 // the init function.
91 LOGI("System server: starting Android runtime.\n");
92
93 AndroidRuntime* runtime = AndroidRuntime::getRuntime();
94
95 LOGI("System server: starting Android services.\n");
96 runtime->callStatic("com/android/server/SystemServer", "init2"); //5 本地服务注册完成后,调用System类中的init2()方法
97
98 // If running in our own process, just go into the thread
99 // pool. Otherwise, call the initialization finished
100 // func to let this process continue its initilization.
101 if (proc->supportsProcesses()) {//6 开启线程用于进程间通讯
102 LOGI("System server: entering thread pool.\n");
103 ProcessState::self()->startThreadPool();
104 IPCThreadState::self()->joinThreadPool();
105 LOGI("System server: exiting thread pool.\n");
106 }
107 return NO_ERROR;
108}
调用SystemServer#init2()方法,在方法中创建线程并启动
437 public static final void init2() {
438 Log.i(TAG, "Entered the Android system server!");
439 Thread thr = new ServerThread();
440 thr.setName("android.server.ServerThread");
441 thr.start();
442 }
ServerThread启动后,将会注册一系列的java层的服务,并开启Looper循环。
3.4 运行新Android应用程序
603 private static void runSelectLoopMode() throws MethodAndArgsCaller {
604 ArrayList<FileDescriptor> fds = new ArrayList();
605 ArrayList<ZygoteConnection> peers = new ArrayList();
606 FileDescriptor[] fdArray = new FileDescriptor[4];
607 //1 将套接字的描述符加到描述符数组中,程序将使用该描述符处理来自外部的连接请求
608 fds.add(sServerSocket.getFileDescriptor());
609 peers.add(null);
610
611 int loopCount = GC_LOOP_COUNT;
612 while (true) {
613 int index;
614
615 /*
616 * Call gc() before we block in select().
617 * It's work that has to be done anyway, and it's better
618 * to avoid making every child do it. It will also
619 * madvise() any free memory as a side-effect.
620 *
621 * Don't call it every time, because walking the entire
622 * heap is a lot of overhead to free a few hundred bytes.
623 */
624 if (loopCount <= 0) {
625 gc();
626 loopCount = GC_LOOP_COUNT;
627 } else {
628 loopCount--;
629 }
630
631
632 try {
633 fdArray = fds.toArray(fdArray);
//2 selectReadable是一个jni函数,该方法用来监视参数传递过来的文件描述符数组,若描述符目录中存在系那个管时间,则返回其在数组中的索引
634 index = selectReadable(fdArray);
635 } catch (IOException ex) {
636 throw new RuntimeException("Error in select()", ex);
637 }
638
639 if (index < 0) {
640 throw new RuntimeException("Error in select()");
641 } else if (index == 0) { //3 该部分用来处理的套接字为0的描述符中发生的输入输出事件
642 ZygoteConnection newPeer = acceptCommandPeer();
643 peers.add(newPeer);
644 fds.add(newPeer.getFileDesciptor());
645 } else {
646 boolean done;
647 done = peers.get(index).runOnce();
648
649 if (done) {
650 peers.remove(index);
651 fds.remove(index);
652 }
653 }
654 }
655 }
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java#runOnce()
167 boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
173 try {
174 args = readArgumentList(); //1读取请求信息
176 }
195 ...
196 int pid;
197
198 try {
199 parsedArgs = new Arguments(args); //2 分析请求信息中的字符串数组
200
201 applyUidSecurityPolicy(parsedArgs, peer);
202 applyDebuggerSecurityPolicy(parsedArgs);
203 applyRlimitSecurityPolicy(parsedArgs, peer);
204 applyCapabilitiesSecurityPolicy(parsedArgs, peer);
205
206 int[][] rlimits = null;
207
208 if (parsedArgs.rlimits != null) {
209 rlimits = parsedArgs.rlimits.toArray(intArray2d);
210 }
211
212 pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, //3 创建新建成,最终调用本地fork()函数
213 parsedArgs.gids, parsedArgs.debugFlags, rlimits);
214 } catch (IllegalArgumentException ex) {
215 logAndPrintError (newStderr, "Invalid zygote arguments", ex);
216 pid = -1;
217 } catch (ZygoteSecurityException ex) {
218 logAndPrintError(newStderr,
219 "Zygote security policy prevents request: ", ex);
220 pid = -1;
221 }
222
223 if (pid == 0) {
224 // in child
225 handleChildProc(parsedArgs, descriptors, newStderr); //4 用来加载新进程所需要的类,并调用该类的main方法
226 // should never happen
227 return true;
228 } else { /* pid != 0 */
229 // in parent...pid of < 0 means failure
230 return handleParentProc(pid, descriptors, parsedArgs);
231 }
232 }
参考资料《Android框架揭秘》