Zygote进程【2】——Zygote的分裂

Zygote的诞生一文中init进程是如何一步步创建Zygote进程的,也了解了Zygote的进程的作用。Zygote进程的诞生对于整个Java世界可以说有着”开天辟地“的作用,它创建了Java虚拟机,并且繁殖了Java世界的核心服务system_server进程,在完成Java世界的初创工作以后,Zygote并没有死去,它只是暂时的沉睡(socket事件堵塞)在那里,一旦有需要(有客户端请求的到来),它便马上起来工作。本文接下来就将分析一下Zygote是如何监听和处理socket事件的。

首先让我们一起来回忆一下Zygote的main方法:

@frameworks/base/core/java/com/Android/internal/os/ZygoteInit.java

  1. public static void main(String argv[]) {
  2. try {
  3. registerZygoteSocket();//注册zygote用的socket
  4. ......
  5. runSelectLoop();//变成守护进程,接收socket信息进行处理
  6. closeServerSocket();
  7. } catch (MethodAndArgsCaller caller) {
  8. caller.run();
  9. } catch (RuntimeException ex) {
  10. Log.e(TAG, "Zygote died with exception", ex);
  11. closeServerSocket();
  12. throw ex;
  13. }
  14. }

main()方法首先在registerZygoteSocket中注册了Zygote的 服务端Socket对象,然后在完成一系列初创工作后调用runSelectLoop进入到死循环中,等待客户端事件的到来。到了这里我们不禁会问,Zygote进程作为服务端,那客户端是谁呢?Zygote接收到客户端连接以后又是如何处理的呢?下面我们就带着这两个问题一起来分析。

客户端请求

@/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

  1. private final void startProcessLocked(ProcessRecord app,
  2. String hostingType, String hostingNameStr) {
  3. ......
  4. try {
  5. ......
  6. // Start the process.  It will either succeed and return a result containing
  7. // the PID of the new process, or else throw a RuntimeException.
  8. Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
  9. app.processName, uid, uid, gids, debugFlags, mountExternal,
  10. app.info.targetSdkVersion, app.info.seinfo, null);
  11. .......
  12. }

@/frameworks/base/core/java/android/os/Process.java

  1. /**
  2. * Start a new process.
  3. *
  4. * <p>If processes are enabled, a new process is created and the
  5. * static main() function of a <var>processClass</var> is executed there.
  6. * The process will continue running after this function returns.
  7. *
  8. * <p>If processes are not enabled, a new thread in the caller's
  9. * process is created and main() of <var>processClass</var> called there.
  10. *
  11. * <p>The niceName parameter, if not an empty string, is a custom name to
  12. * give to the process instead of using processClass.  This allows you to
  13. * make easily identifyable processes even if you are using the same base
  14. * <var>processClass</var> to start them.
  15. *
  16. * @param processClass The class to use as the process's main entry
  17. *                     point.
  18. * @param niceName A more readable name to use for the process.
  19. * @param uid The user-id under which the process will run.
  20. * @param gid The group-id under which the process will run.
  21. * @param gids Additional group-ids associated with the process.
  22. * @param debugFlags Additional flags.
  23. * @param targetSdkVersion The target SDK version for the app.
  24. * @param seInfo null-ok SE Android information for the new process.
  25. * @param zygoteArgs Additional arguments to supply to the zygote process.
  26. *
  27. * @return An object that describes the result of the attempt to start the process.
  28. * @throws RuntimeException on fatal start failure
  29. *
  30. * {@hide}
  31. */
  32. public static final ProcessStartResult start(final String processClass,
  33. final String niceName,
  34. int uid, int gid, int[] gids,
  35. int debugFlags, int mountExternal,
  36. int targetSdkVersion,
  37. String seInfo,
  38. String[] zygoteArgs) {
  39. try {
  40. return startViaZygote(processClass, niceName, uid, gid, gids,
  41. debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
  42. } catch (ZygoteStartFailedEx ex) {
  43. Log.e(LOG_TAG,
  44. "Starting VM process through Zygote failed");
  45. throw new RuntimeException(
  46. "Starting VM process through Zygote failed", ex);
  47. }
  48. }

startViaZygote()方法的实现如下:

  1. /**
  2. * Starts a new process via the zygote mechanism.
  3. *
  4. * @param processClass Class name whose static main() to run
  5. * @param niceName 'nice' process name to appear in ps
  6. * @param uid a POSIX uid that the new process should setuid() to
  7. * @param gid a POSIX gid that the new process shuold setgid() to
  8. * @param gids null-ok; a list of supplementary group IDs that the
  9. * new process should setgroup() to.
  10. * @param debugFlags Additional flags.
  11. * @param targetSdkVersion The target SDK version for the app.
  12. * @param seInfo null-ok SE Android information for the new process.
  13. * @param extraArgs Additional arguments to supply to the zygote process.
  14. * @return An object that describes the result of the attempt to start the process.
  15. * @throws ZygoteStartFailedEx if process start failed for any reason
  16. */
  17. private static ProcessStartResult startViaZygote(final String processClass,
  18. final String niceName,
  19. final int uid, final int gid,
  20. final int[] gids,
  21. int debugFlags, int mountExternal,
  22. int targetSdkVersion,
  23. String seInfo,
  24. String[] extraArgs)
  25. throws ZygoteStartFailedEx {
  26. synchronized(Process.class) {
  27. ArrayList<String> argsForZygote = new ArrayList<String>();
  28. // --runtime-init, --setuid=, --setgid=,
  29. // and --setgroups= must go first
  30. argsForZygote.add("--runtime-init");
  31. argsForZygote.add("--setuid=" + uid);
  32. argsForZygote.add("--setgid=" + gid);
  33. if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
  34. argsForZygote.add("--enable-jni-logging");
  35. }
  36. if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
  37. argsForZygote.add("--enable-safemode");
  38. }
  39. if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
  40. argsForZygote.add("--enable-debugger");
  41. }
  42. if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
  43. argsForZygote.add("--enable-checkjni");
  44. }
  45. if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
  46. argsForZygote.add("--enable-assert");
  47. }
  48. if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
  49. argsForZygote.add("--mount-external-multiuser");
  50. } else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL) {
  51. argsForZygote.add("--mount-external-multiuser-all");
  52. }
  53. argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
  54. //TODO optionally enable debuger
  55. //argsForZygote.add("--enable-debugger");
  56. // --setgroups is a comma-separated list
  57. if (gids != null && gids.length > 0) {
  58. StringBuilder sb = new StringBuilder();
  59. sb.append("--setgroups=");
  60. int sz = gids.length;
  61. for (int i = 0; i < sz; i++) {
  62. if (i != 0) {
  63. sb.append(',');
  64. }
  65. sb.append(gids[i]);
  66. }
  67. argsForZygote.add(sb.toString());
  68. }
  69. if (niceName != null) {
  70. argsForZygote.add("--nice-name=" + niceName);
  71. }
  72. if (seInfo != null) {
  73. argsForZygote.add("--seinfo=" + seInfo);
  74. }
  75. argsForZygote.add(processClass);
  76. if (extraArgs != null) {
  77. for (String arg : extraArgs) {
  78. argsForZygote.add(arg);
  79. }
  80. }
  81. return zygoteSendArgsAndGetResult(argsForZygote);
  82. }
  83. }

startViaZygote的绝大部分代码都在处理传递到Zygote中的参数,与Zygote通信通过zygoteSendArgsAndGetResult()方法完成:

  1. /**
  2. * Sends an argument list to the zygote process, which starts a new child
  3. * and returns the child's pid. Please note: the present implementation
  4. * replaces newlines in the argument list with spaces.
  5. * @param args argument list
  6. * @return An object that describes the result of the attempt to start the process.
  7. * @throws ZygoteStartFailedEx if process start failed for any reason
  8. */
  9. private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args)
  10. throws ZygoteStartFailedEx {
  11. openZygoteSocketIfNeeded();//确保和Zygote通信的socket已被打开
  12. try {
  13. /**
  14. * See com.android.internal.os.ZygoteInit.readArgumentList()
  15. * Presently the wire format to the zygote process is:
  16. * a) a count of arguments (argc, in essence)
  17. * b) a number of newline-separated argument strings equal to count
  18. *
  19. * After the zygote process reads these it will write the pid of
  20. * the child or -1 on failure, followed by boolean to
  21. * indicate whether a wrapper process was used.
  22. */
  23. sZygoteWriter.write(Integer.toString(args.size()));
  24. sZygoteWriter.newLine();
  25. int sz = args.size();
  26. for (int i = 0; i < sz; i++) {//发送请求参数到Zygote
  27. String arg = args.get(i);
  28. if (arg.indexOf('\n') >= 0) {
  29. throw new ZygoteStartFailedEx(
  30. "embedded newlines not allowed");
  31. }
  32. sZygoteWriter.write(arg);
  33. sZygoteWriter.newLine();
  34. }
  35. sZygoteWriter.flush();
  36. // Should there be a timeout on this?
  37. ProcessStartResult result = new ProcessStartResult();
  38. result.pid = sZygoteInputStream.readInt();//Zygote处理完成会返回子进程的pid(即要创建的进程)
  39. if (result.pid < 0) {
  40. throw new ZygoteStartFailedEx("fork() failed");
  41. }
  42. result.usingWrapper = sZygoteInputStream.readBoolean();
  43. return result;
  44. } catch (IOException ex) {
  45. try {
  46. if (sZygoteSocket != null) {
  47. sZygoteSocket.close();
  48. }
  49. } catch (IOException ex2) {
  50. // we're going to fail anyway
  51. Log.e(LOG_TAG,"I/O exception on routine close", ex2);
  52. }
  53. sZygoteSocket = null;
  54. throw new ZygoteStartFailedEx(ex);
  55. }
  56. }

到这里位置,客户端请求Zygote创建进程的请求就发送出去了,Zygote会返回进行的pid给客户端(ActivityMangerService)。由于ActivityMangerService在SystemServer进程中,所以这里即SystemServer进程通过socket向Zygote发送了信息。

接下来,我们看一下看一下Zygote是如何处理客户端请求的。

处理客户端请求

  1. /**
  2. * Runs the zygote process's select loop. Accepts new connections as
  3. * they happen, and reads commands from connections one spawn-request's
  4. * worth at a time.
  5. *
  6. * @throws MethodAndArgsCaller in a child process when a main() should
  7. * be executed.
  8. */
  9. private static void runSelectLoop() throws MethodAndArgsCaller {
  10. <span style="white-space:pre">  </span>......
  11. <span style="white-space:pre">  </span>
  12. while (true) {//死循环
  13. ......
  14. if (index < 0) {
  15. throw new RuntimeException("Error in select()");
  16. } else if (index == 0) {//index==0表示selcet接收到的是Zygote的socket的事件
  17. ZygoteConnection newPeer = acceptCommandPeer();
  18. peers.add(newPeer);
  19. fds.add(newPeer.getFileDesciptor());
  20. } else {//调用ZygoteConnection对象的runOnce方法,ZygoteConnection是在index == 0时被添加到peers的
  21. boolean done;
  22. done = peers.get(index).runOnce();
  23. if (done) {
  24. peers.remove(index);
  25. fds.remove(index);
  26. }
  27. }
  28. }
  29. }

每当有请求过来时,Zygote都会调用ZygoteConnection的runOnce()方法处理:

@/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

  1. /**
  2. * Reads one start command from the command socket. If successful,
  3. * a child is forked and a {@link ZygoteInit.MethodAndArgsCaller}
  4. * exception is thrown in that child while in the parent process,
  5. * the method returns normally. On failure, the child is not
  6. * spawned and messages are printed to the log and stderr. Returns
  7. * a boolean status value indicating whether an end-of-file on the command
  8. * socket has been encountered.
  9. *
  10. * @return false if command socket should continue to be read from, or
  11. * true if an end-of-file has been encountered.
  12. * @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main()
  13. * method in child process
  14. */
  15. boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
  16. String args[];
  17. Arguments parsedArgs = null;
  18. FileDescriptor[] descriptors;
  19. try {
  20. args = readArgumentList();//读取客户端发送过来的参数
  21. descriptors = mSocket.getAncillaryFileDescriptors();
  22. } catch (IOException ex) {
  23. Log.w(TAG, "IOException on command socket " + ex.getMessage());
  24. closeSocket();
  25. return true;
  26. }
  27. if (args == null) {
  28. // EOF reached.
  29. closeSocket();
  30. return true;
  31. }
  32. /** the stderr of the most recent request, if avail */
  33. PrintStream newStderr = null;
  34. if (descriptors != null && descriptors.length >= 3) {
  35. newStderr = new PrintStream(
  36. new FileOutputStream(descriptors[2]));
  37. }
  38. int pid = -1;
  39. FileDescriptor childPipeFd = null;
  40. FileDescriptor serverPipeFd = null;
  41. try {
  42. parsedArgs = new Arguments(args);
  43. applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
  44. applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
  45. applyCapabilitiesSecurityPolicy(parsedArgs, peer, peerSecurityContext);
  46. applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
  47. applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext);
  48. applyDebuggerSystemProperty(parsedArgs);
  49. applyInvokeWithSystemProperty(parsedArgs);
  50. int[][] rlimits = null;
  51. if (parsedArgs.rlimits != null) {
  52. rlimits = parsedArgs.rlimits.toArray(intArray2d);
  53. }
  54. if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
  55. FileDescriptor[] pipeFds = Libcore.os.pipe();
  56. childPipeFd = pipeFds[1];
  57. serverPipeFd = pipeFds[0];
  58. ZygoteInit.setCloseOnExec(serverPipeFd, true);
  59. }
  60. //fork一个新进程
  61. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
  62. parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
  63. parsedArgs.niceName);
  64. } catch (IOException ex) {
  65. logAndPrintError(newStderr, "Exception creating pipe", ex);
  66. } catch (ErrnoException ex) {
  67. logAndPrintError(newStderr, "Exception creating pipe", ex);
  68. } catch (IllegalArgumentException ex) {
  69. logAndPrintError(newStderr, "Invalid zygote arguments", ex);
  70. } catch (ZygoteSecurityException ex) {
  71. logAndPrintError(newStderr,
  72. "Zygote security policy prevents request: ", ex);
  73. }
  74. try {
  75. if (pid == 0) {//子进程
  76. // in child
  77. IoUtils.closeQuietly(serverPipeFd);
  78. serverPipeFd = null;
  79. handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
  80. // should never get here, the child is expected to either
  81. // throw ZygoteInit.MethodAndArgsCaller or exec().
  82. return true;
  83. } else {//父进程
  84. // in parent...pid of < 0 means failure
  85. IoUtils.closeQuietly(childPipeFd);
  86. childPipeFd = null;
  87. return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
  88. }
  89. } finally {
  90. IoUtils.closeQuietly(childPipeFd);
  91. IoUtils.closeQuietly(serverPipeFd);
  92. }
  93. }

Zygote在处理客户端请求时会fork一个新的进程,接下来首先看一下handleChildProc()方法:

  1. /**
  2. * Handles post-fork setup of child proc, closing sockets as appropriate,
  3. * reopen stdio as appropriate, and ultimately throwing MethodAndArgsCaller
  4. * if successful or returning if failed.
  5. *
  6. * @param parsedArgs non-null; zygote args
  7. * @param descriptors null-ok; new file descriptors for stdio if available.
  8. * @param pipeFd null-ok; pipe for communication back to Zygote.
  9. * @param newStderr null-ok; stream to use for stderr until stdio
  10. * is reopened.
  11. *
  12. * @throws ZygoteInit.MethodAndArgsCaller on success to
  13. * trampoline to code that invokes static main.
  14. */
  15. private void handleChildProc(Arguments parsedArgs,
  16. FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
  17. throws ZygoteInit.MethodAndArgsCaller {
  18. closeSocket();//关闭子进程中,从Zygote fork过来的服务端socket
  19. ZygoteInit.closeServerSocket();
  20. .....
  21. if (parsedArgs.niceName != null) {
  22. Process.setArgV0(parsedArgs.niceName);
  23. }
  24. if (parsedArgs.runtimeInit) {//从startViaZygote可知传入了--runtime-init参数,所以这里为true
  25. if (parsedArgs.invokeWith != null) {//没有传入--invoke-with,所以这里走的是else的逻辑
  26. WrapperInit.execApplication(parsedArgs.invokeWith,
  27. parsedArgs.niceName, parsedArgs.targetSdkVersion,
  28. pipeFd, parsedArgs.remainingArgs);
  29. } else {
  30. RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
  31. parsedArgs.remainingArgs);
  32. }
  33. } else {
  34. ......
  35. }
  36. }

zygoteInit()方法的实现在RuntimeInit类中:

@/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

  1. /**
  2. * The main function called when started through the zygote process. This
  3. * could be unified with main(), if the native code in nativeFinishInit()
  4. * were rationalized with Zygote startup.<p>
  5. *
  6. * Current recognized args:
  7. * <ul>
  8. *   <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
  9. * </ul>
  10. *
  11. * @param targetSdkVersion target SDK version
  12. * @param argv arg strings
  13. */
  14. public static final void zygoteInit(int targetSdkVersion, String[] argv)
  15. throws ZygoteInit.MethodAndArgsCaller {
  16. if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
  17. redirectLogStreams();//将System.out 和 System.err 输出重定向到Android 的Log系统
  18. /*
  19. * 初始化了一些系统属性,其中最重要的一点就是设置了一个未捕捉异常的handler,
  20. * 当代码有任何未知异常,就会执行它,
  21. * 调试过Android代码的同学经常看到的"*** FATAL EXCEPTION IN SYSTEM PROCESS" 打印就出自这里
  22. */
  23. commonInit();
  24. /*
  25. * 最终会调用app_main的onZygoteInit函数
  26. * 这里的作用是在新进程中引入Binder,也就说通过nativeZygoteInit以后,新的进程就可以使用Binder进程通信了
  27. */
  28. nativeZygoteInit();
  29. applicationInit(targetSdkVersion, argv);//应用初始化
  30. }

接下来继续分析applicationInit(),走完进程启动的整个过程,然后再回头分析一下commonInit和nativeZygoteInit的实现。applicationInit的实现如下:

  1. private static void applicationInit(int targetSdkVersion, String[] argv)
  2. throws ZygoteInit.MethodAndArgsCaller {
  3. // If the application calls System.exit(), terminate the process
  4. // immediately without running any shutdown hooks.  It is not possible to
  5. // shutdown an Android application gracefully.  Among other things, the
  6. // Android runtime shutdown hooks close the Binder driver, which can cause
  7. // leftover running threads to crash before the process actually exits.
  8. nativeSetExitWithoutCleanup(true);
  9. // We want to be fairly aggressive about heap utilization, to avoid
  10. // holding on to a lot of memory that isn't needed.
  11. VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
  12. VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
  13. final Arguments args;
  14. try {
  15. args = new Arguments(argv);
  16. } catch (IllegalArgumentException ex) {
  17. Slog.e(TAG, ex.getMessage());
  18. // let the process exit
  19. return;
  20. }
  21. // Remaining arguments are passed to the start class's static main
  22. invokeStaticMain(args.startClass, args.startArgs);
  23. }

在applicationInit()的最后,会通过调用invokeStaticMain来调用args.startClass这个类的main()方法。在前面介绍socket的客户端代码时,在startProcessLocked()中传入的这个类为Zygote进程【2】——Zygote的分裂Zygote进程【2】——Zygote的分裂

  1. /**
  2. * Invokes a static "main(argv[]) method on class "className".
  3. * Converts various failing exceptions into RuntimeExceptions, with
  4. * the assumption that they will then cause the VM instance to exit.
  5. *
  6. * @param className Fully-qualified class name
  7. * @param argv Argument vector for main()
  8. */
  9. private static void invokeStaticMain(String className, String[] argv)
  10. throws ZygoteInit.MethodAndArgsCaller {
  11. Class<?> cl;
  12. try {
  13. cl = Class.forName(className);
  14. } catch (ClassNotFoundException ex) {
  15. throw new RuntimeException(
  16. "Missing class when invoking static main " + className,
  17. ex);
  18. }
  19. Method m;
  20. try {
  21. m = cl.getMethod("main", new Class[] { String[].class });
  22. } catch (NoSuchMethodException ex) {
  23. throw new RuntimeException(
  24. "Missing static main on " + className, ex);
  25. } catch (SecurityException ex) {
  26. throw new RuntimeException(
  27. "Problem getting static main on " + className, ex);
  28. }
  29. int modifiers = m.getModifiers();
  30. if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
  31. throw new RuntimeException(
  32. "Main method is not public and static on " + className);
  33. }
  34. /*
  35. * This throw gets caught in ZygoteInit.main(), which responds
  36. * by invoking the exception's run() method. This arrangement
  37. * clears up all the stack frames that were required in setting
  38. * up the process.
  39. */
  40. throw new ZygoteInit.MethodAndArgsCaller(m, argv);
  41. }

这个方法本身功能就是调用ActivityThread类的main(),没什么可说的。不过需要注意一下的是这里的调用方式十分特别,并没有采取常规的反射调用,而是通过抛出异常的方式调用ActivityThread的main()函数。这里抛出的ZygoteInit.MethodAndArgsCaller异常会在ZygoteInit.main()中被捕获处理。

  1. public static void main(String argv[]) {
  2. try {
  3. ......
  4. } catch (MethodAndArgsCaller caller) {
  5. caller.run();
  6. } catch (RuntimeException ex) {
  7. ......
  8. }
  9. }

这里需要注意的是:捕获异常是在子进程(即新的进程,不是Zygote进程)中的动作。还记得前面介绍的runOnce()方法吗?我们在runOnce中创建了一个新的进程。如果读者还有不明白这里为什么是在子进程,可以自行学习Linux
fork()的原理。好了,继续..... 看一下MethodAndArgsCaller的代码:

@/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

  1. /**
  2. * Helper exception class which holds a method and arguments and
  3. * can call them. This is used as part of a trampoline to get rid of
  4. * the initial process setup stack frames.
  5. */
  6. public static class MethodAndArgsCaller extends Exception
  7. implements Runnable {
  8. /** method to call */
  9. private final Method mMethod;
  10. /** argument array */
  11. private final String[] mArgs;
  12. public MethodAndArgsCaller(Method method, String[] args) {
  13. mMethod = method;
  14. mArgs = args;
  15. }
  16. public void run() {
  17. try {
  18. mMethod.invoke(null, new Object[] { mArgs });
  19. } catch (IllegalAccessException ex) {
  20. throw new RuntimeException(ex);
  21. } catch (InvocationTargetException ex) {
  22. Throwable cause = ex.getCause();
  23. if (cause instanceof RuntimeException) {
  24. throw (RuntimeException) cause;
  25. } else if (cause instanceof Error) {
  26. throw (Error) cause;
  27. }
  28. throw new RuntimeException(ex);
  29. }
  30. }
  31. }

可以看出最后还是会调用invoke方法通过反射的方式调用ActivityThread的main方法。

到了这里,相信大家都会有一个疑问:既然最后还是通过invoke来反射调用main方法,那绕这一大圈子到底在折腾什么?

有疑问的读者,有没有去思考过另外一个问题:我们为什么要通过Zygote去创建进程,而不是直接创建一个新的进程出来呢?这就要从Zygote创建进程的机制来解释。相信我们还记得在ZygoteInit的main函数中我们通过preload来预加载类和资源。所以这些被预加载的类和资源都存在于Zygote进程中。在通过Zygote创建进程时,我们是通过fork来创建的。 一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同,相当于克隆了一个自己。所以,Zygote通过fork的方式创建新的应用进程的同时,会将对系统的(主要是framework中的)一些类和资源的引用同时复制给子进程,这样子进程中就可以使用这些资源了。这也是为什么所有的应用程序可以共享Framework中的类和资源的原因。

在明白了Zygote机制后,对应为什么这里会以抛出异常的方式调用ActivityThread(应用程序入口)的main()方法,就变得容易理解了。在Java中,我们进行一些列的方法调用的时候,系统会为我们在内存中维护一个调用栈,栈底是发起调用的方法,栈顶是当前正在被调用的方法。在栈顶的方法调用完成后,会逐级返回调用它的方法,最后调用会回到最开始的方法中,然后调用栈就被销毁了。在Zygote处理客户端事件的时候,沿着各种方法一路调用下来,如果在调用ActivityThread中的main()时,直接使用invoke,那么在invoke结束后,整个调用过程会递归返回,最后发起方得到调用结果,调用栈被销毁。然后每次的调用都会重复刚才的那个过程,这就造成了极大的浪费。采用异常的方式,可以保证调用栈不会被销毁,这样每次fork时就可以共享。

好了,到此为止Zygote的分裂过程就介绍完成了。

上一篇:SQL Server窗口函数:ROWS与RANGE


下一篇:GitHub 中国区前 100 名到底是什么样的人?