跳转至

Zygote 孵化流程

本文暂未考虑 fork child zygote 的情况

1. ZygoteInit 初始化

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

ZygoteInit 的主要流程是预加载资源,如果参数里有 --start-system-server 则孵化 SystemServer,最后启动 runSelectLoop 进入循环等待的创建请求。

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
// 检查参数 line 848:860
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }
// 预加载资源供后续孵化用 line 879:889
            // In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first fork.
            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                        SystemClock.uptimeMillis());
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            }
// 启动 runSelectLoop 循环等待创建请求 line 917:933
            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with fatal exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }

ZygoteInit 的 main 启动中会判断了传入参数有没有 --start-system-server,如果有则会孵化 SystemServer 进程。

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
// line 817
    public static void main(String[] argv) {
// 检查 argv 里是否存在 `--start-system-server` 设置 startSystemServer 标志 line 848:850
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
// 孵化 SystemServer line 902:913
            zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
// zygote 启动时请求的 forkSystemServer 方法 line 685:692
    /**
     * Prepare the arguments and forks for the system server process.
     *
     * @return A {@code Runnable} that provides an entrypoint into system_server code in the child
     * process; {@code null} in the parent.
     */
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
// 配置 fork 相关参数 line 718:730

        /* Hardcoded command line to start the system server */
        String[] args = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3005,3006,3007,3009,3010,3011,3012",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
// 调用 Zygote.forkSystemServer 方法 line 776:799

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;

2. Zygote 监听处理其他进程的 fork 请求

当别的应用需要孵化一个新的进程时,会通过本地 socket 向 Zygote 发送请求,Zygote 收到请求后会执行 fork 来创建新的进程。

具体流程如下:

  1. ZygoteServer 监听请求
    上文提到 ZygoteInit 启动了 runSelectLoop 方法负责监听和管理请求,代码中可以看出将具体的处理工作交给 ZygoteConnection
    /frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
    // line 388:434
        /**
         * Runs the zygote process's select loop. Accepts new connections as
         * they happen, and reads commands from connections one spawn-request's
         * worth at a time.
         * @param abiList list of ABIs supported by this zygote.
         */
        Runnable runSelectLoop(String abiList) {
            ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
            ArrayList<ZygoteConnection> peers = new ArrayList<>();
    
            socketFDs.add(mZygoteSocket.getFileDescriptor());
            peers.add(null);
    
            mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
    
            while (true) {
                fetchUsapPoolPolicyPropsWithMinInterval();
                mUsapPoolRefillAction = UsapPoolRefillAction.NONE;
    
                int[] usapPipeFDs = null;
                StructPollfd[] pollFDs;
    
                // Allocate enough space for the poll structs, taking into account
                // the state of the USAP pool for this Zygote (could be a
                // regular Zygote, a WebView Zygote, or an AppZygote).
                if (mUsapPoolEnabled) {
                    usapPipeFDs = Zygote.getUsapPipeFDs();
                    pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
                } else {
                    pollFDs = new StructPollfd[socketFDs.size()];
                }
    
                /*
                 * For reasons of correctness the USAP pool pipe and event FDs
                 * must be processed before the session and server sockets.  This
                 * is to ensure that the USAP pool accounting information is
                 * accurate when handling other requests like API deny list
                 * exemptions.
                 */
    
                int pollIndex = 0;
                for (FileDescriptor socketFD : socketFDs) {
                    pollFDs[pollIndex] = new StructPollfd();
                    pollFDs[pollIndex].fd = socketFD;
                    pollFDs[pollIndex].events = (short) POLLIN;
                    ++pollIndex;
                }
    // ...
    // line 485:548
                try {
                    pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
                } catch (ErrnoException ex) {
                    throw new RuntimeException("poll failed", ex);
                }
    
                if (pollReturnValue == 0) {
                    // The poll returned zero results either when the timeout value has been exceeded
                    // or when a non-blocking poll is issued and no FDs are ready.  In either case it
                    // is time to refill the pool.  This will result in a duplicate assignment when
                    // the non-blocking poll returns zero results, but it avoids an additional
                    // conditional in the else branch.
                    mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
                    mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;
    
                } else {
                    boolean usapPoolFDRead = false;
    
                    while (--pollIndex >= 0) {
                        if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                            continue;
                        }
    
                        if (pollIndex == 0) {
                            // Zygote server socket
                            ZygoteConnection newPeer = acceptCommandPeer(abiList);
                            peers.add(newPeer);
                            socketFDs.add(newPeer.getFileDescriptor());
                        } else if (pollIndex < usapPoolEventFDIndex) {
                            // Session socket accepted from the Zygote server socket
    
                            try {
                                ZygoteConnection connection = peers.get(pollIndex);
                                boolean multipleForksOK = !isUsapPoolEnabled()
                                        && ZygoteHooks.isIndefiniteThreadSuspensionSafe();
                                final Runnable command =
                                        connection.processCommand(this, multipleForksOK);
    
                                // TODO (chriswailes): Is this extra check necessary?
                                if (mIsForkChild) {
                                    // We're in the child. We should always have a command to run at
                                    // this stage if processCommand hasn't called "exec".
                                    if (command == null) {
                                        throw new IllegalStateException("command == null");
                                    }
    
                                    return command;
                                } else {
                                    // We're in the server - we should never have any commands to run.
                                    if (command != null) {
                                        throw new IllegalStateException("command != null");
                                    }
    
                                    // We don't know whether the remote side of the socket was closed or
                                    // not until we attempt to read from it from processCommand. This
                                    // shows up as a regular POLLIN event in our regular processing
                                    // loop.
                                    if (connection.isClosedByPeer()) {
                                        connection.closeSocket();
                                        peers.remove(pollIndex);
                                        socketFDs.remove(pollIndex);
                                    }
                                }
                            } catch (Exception e) {
    
    上面通过 Os.poll 来监听套接字的事件,当有新的连接时,创建一个 ZygoteConnection 来处理这个连接。
  2. ZygoteConnection 处理连接
    ZygoteConnection 负责解析请求参数,并调用 Zygote.forkAndSpecialize 来执行 fork 操作。

    /frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
    // line 111:138
        /**
         * Reads a command from the command socket. If a child is successfully forked, a
         * {@code Runnable} that calls the childs main method (or equivalent) is returned in the child
         * process. {@code null} is always returned in the parent process (the zygote).
         * If multipleOK is set, we may keep processing additional fork commands before returning.
         *
         * If the client closes the socket, an {@code EOF} condition is set, which callers can test
         * for by calling {@code ZygoteConnection.isClosedByPeer}.
         */
        Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
            ZygoteArguments parsedArgs;
    
            try (ZygoteCommandBuffer argBuffer = new ZygoteCommandBuffer(mSocket)) {
                while (true) {
                    try {
                        parsedArgs = ZygoteArguments.getInstance(argBuffer);
                        // Keep argBuffer around, since we need it to fork.
                    } catch (IOException ex) {
                        throw new IllegalStateException("IOException on command socket", ex);
                    }
                    if (parsedArgs == null) {
                        isEof = true;
                        return null;
                    }
    
                    int pid;
                    FileDescriptor childPipeFd = null;
                    FileDescriptor serverPipeFd = null;
    // ...
    // 可以看到调用 Native 层的 fork 逻辑 line 248:276
                        pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,
                                parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,
                                parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,
                                fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                                parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,
                                parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,
                                parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
                                parsedArgs.mBindMountAppStorageDirs,
                                parsedArgs.mBindMountSyspropOverrides);
    
                        try {
                            if (pid == 0) {
                                // in child
                                zygoteServer.setForkChild();
    
                                zygoteServer.closeServerSocket();
                                IoUtils.closeQuietly(serverPipeFd);
                                serverPipeFd = null;
    
                                return handleChildProc(parsedArgs, childPipeFd,
                                        parsedArgs.mStartChildZygote);
                            } else {
                                // In the parent. A pid < 0 indicates a failure and will be handled in
                                // handleParentProc.
                                IoUtils.closeQuietly(childPipeFd);
                                childPipeFd = null;
                                handleParentProc(pid, serverPipeFd);
                                return null;
                            }
    

  3. Zygote 执行 Fork
    forkAndSpecialize 方法会调用 native 方法 nativeForkAndSpecialize 来真正执行 fork

    我们可以对比一下孵化普通应用进程 (forkAndSpecialize) 和孵化 SystemServer (forkSystemServer) 的代码,它们最终都依赖 native 方法。

    /frameworks/base/core/java/com/android/internal/os/Zygote.java
    // line 368:403
        static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
                int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
                int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
                boolean isTopApp, String[] pkgDataInfoList, String[] allowlistedDataInfoList,
                boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs,
                boolean bindMountSyspropOverrides) {
            ZygoteHooks.preFork();
    
            int pid = nativeForkAndSpecialize(
                    uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                    fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
                    pkgDataInfoList, allowlistedDataInfoList, bindMountAppDataDirs,
                    bindMountAppStorageDirs, bindMountSyspropOverrides);
            if (pid == 0) {
                // Note that this event ends at the end of handleChildProc,
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
    
                // If no GIDs were specified, don't make any permissions changes based on groups.
                if (gids != null && gids.length > 0) {
                    NetworkUtilsInternal.setAllowNetworkingForProcess(containsInetGid(gids));
                }
            }
    
            // Set the Java Language thread priority to the default value for new apps.
            Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
    
            ZygoteHooks.postForkCommon();
            return pid;
        }
    
        private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
                int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
                int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
                String appDataDir, boolean isTopApp, String[] pkgDataInfoList,
                String[] allowlistedDataInfoList, boolean bindMountAppDataDirs,
                boolean bindMountAppStorageDirs, boolean bindMountSyspropOverrides);
    
    /frameworks/base/core/java/com/android/internal/os/Zygote.java
    // line 501:517
        static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
                int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
            ZygoteHooks.preFork();
    
            int pid = nativeForkSystemServer(
                    uid, gid, gids, runtimeFlags, rlimits,
                    permittedCapabilities, effectiveCapabilities);
    
            // Set the Java Language thread priority to the default value for new apps.
            Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
    
            ZygoteHooks.postForkCommon();
            return pid;
        }
    
        private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
                int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
    

3. Native 层:执行 Fork

Java 层的 native 方法最终会调用到 C++ 层的 ForkCommon 函数来完成进程的创建。

/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
// line 2530:2585
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint runtime_flags,
        jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name,
        jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
        jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
        jobjectArray pkg_data_info_list, jobjectArray allowlisted_data_info_list,
        jboolean mount_data_dirs, jboolean mount_storage_dirs, jboolean mount_sysprop_overrides) {
    jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
    jlong bounding_capabilities = CalculateBoundingCapabilities(env, uid, gid, gids);

    if (UNLIKELY(managed_fds_to_close == nullptr)) {
      zygote::ZygoteFailure(env, "zygote", nice_name,
                            "Zygote received a null fds_to_close vector.");
    }

    std::vector<int> fds_to_close =
        ExtractJIntArray(env, "zygote", nice_name, managed_fds_to_close).value();
    std::vector<int> fds_to_ignore =
        ExtractJIntArray(env, "zygote", nice_name, managed_fds_to_ignore)
            .value_or(std::vector<int>());

    std::vector<int> usap_pipes = MakeUsapPipeReadFDVector();

    fds_to_close.insert(fds_to_close.end(), usap_pipes.begin(), usap_pipes.end());
    fds_to_ignore.insert(fds_to_ignore.end(), usap_pipes.begin(), usap_pipes.end());

    fds_to_close.push_back(gUsapPoolSocketFD);

    if (gUsapPoolEventFD != -1) {
      fds_to_close.push_back(gUsapPoolEventFD);
      fds_to_ignore.push_back(gUsapPoolEventFD);
    }

    if (gSystemServerSocketFd != -1) {
        fds_to_close.push_back(gSystemServerSocketFd);
        fds_to_ignore.push_back(gSystemServerSocketFd);
    }

    if (gPreloadFds && gPreloadFdsExtracted) {
        fds_to_ignore.insert(fds_to_ignore.end(), gPreloadFds->begin(), gPreloadFds->end());
    }

    pid_t pid = zygote::ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore,
                                   true);

    if (pid == 0) {
        SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities,
                         bounding_capabilities, mount_external, se_info, nice_name, false,
                         is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
                         is_top_app == JNI_TRUE, pkg_data_info_list, allowlisted_data_info_list,
                         mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE,
                         mount_sysprop_overrides == JNI_TRUE);
    }
    return pid;
}
/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
// line 2587:2643
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,
        jlong effective_capabilities) {
  ATRACE_CALL();
  std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),
                   fds_to_ignore(fds_to_close);

  fds_to_close.push_back(gUsapPoolSocketFD);

  if (gUsapPoolEventFD != -1) {
    fds_to_close.push_back(gUsapPoolEventFD);
    fds_to_ignore.push_back(gUsapPoolEventFD);
  }

  if (gSystemServerSocketFd != -1) {
      fds_to_close.push_back(gSystemServerSocketFd);
      fds_to_ignore.push_back(gSystemServerSocketFd);
  }

  pid_t pid = zygote::ForkCommon(env, true,
                                 fds_to_close,
                                 fds_to_ignore,
                                 true);
  if (pid == 0) {
      // System server prcoess does not need data isolation so no need to
      // know pkg_data_info_list.
      SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities,
                       effective_capabilities, 0, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
                       false, nullptr, nullptr, /* is_top_app= */ false,
                       /* pkg_data_info_list */ nullptr,
                       /* allowlisted_data_info_list */ nullptr, false, false, false);
  } else if (pid > 0) {
      // The zygote process checks whether the child process has died or not.
      ALOGI("System server process %d has been created", pid);
      gSystemServerPid = pid;
      // There is a slight window that the system server process has crashed
      // but it went unnoticed because we haven't published its pid yet. So
      // we recheck here just to make sure that all is well.
      int status;
      if (waitpid(pid, &status, WNOHANG) == pid) {
          ALOGE("System server process %d has died. Restarting Zygote!", pid);
          RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
      }

      if (UsePerAppMemcg()) {
          // Assign system_server to the correct memory cgroup.
          // Not all devices mount memcg so check if it is mounted first
          // to avoid unnecessarily printing errors and denials in the logs.
          if (!SetTaskProfiles(pid, std::vector<std::string>{"SystemMemoryProcess"})) {
              ALOGE("couldn't add process %d into system memcg group", pid);
          }
      }
  }
  return pid;
}

可以看到,它们都调用了 ForkCommon 方法。

我们来看 ForkCommon 的实现方法:

/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
// line 2421:2523
// Utility routine to fork a process from the zygote.
NO_STACK_PROTECTOR
pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,
                         const std::vector<int>& fds_to_close,
                         const std::vector<int>& fds_to_ignore,
                         bool is_priority_fork,
                         bool purge) {
//...
  pid_t pid = fork();

  if (pid == 0) {
    if (is_priority_fork) {
      setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
    } else {
      setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);
    }
//...
  return pid;
}

ForkCommon 调用了底层的 fork() 方法,并且接受了返回的 pid。

4. Fork 完成到应用进程启动

上文中在 fork 完成后,在子进程中会走进 handleChildProchandleSystemServerProcess 我们来看这两个方法

/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
// line 504:536
    private Runnable handleChildProc(ZygoteArguments parsedArgs,
            FileDescriptor pipeFd, boolean isZygote) {
        /*
         * By the time we get here, the native code has closed the two actual Zygote
         * socket connections, and substituted /dev/null in their place.  The LocalSocket
         * objects still need to be closed properly.
         */

        closeSocket();

        Zygote.setAppProcessName(parsedArgs, TAG);

        // End of the postFork event.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        if (parsedArgs.mInvokeWith != null) {
            WrapperInit.execApplication(parsedArgs.mInvokeWith,
                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(),
                    pipeFd, parsedArgs.mRemainingArgs);

            // Should not get here.
            throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
        } else {
            if (!isZygote) {
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mDisabledCompatChanges,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            } else {
                return ZygoteInit.childZygoteInit(
                        parsedArgs.mRemainingArgs  /* classLoader */);
            }
        }
    }
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
// line 484:563
    /**
     * Finish remaining work for the newly forked system server process.
     */
    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Os.umask(S_IRWXG | S_IRWXO);

        if (parsedArgs.mNiceName != null) {
            Process.setArgV0(parsedArgs.mNiceName);
        }

        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
            // Capturing profiles is only supported for debug or eng builds since selinux normally
            // prevents it.
            if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
                try {
                    Log.d(TAG, "Preparing system server profile");
                    final String standaloneSystemServerJars =
                            Os.getenv("STANDALONE_SYSTEMSERVER_JARS");
                    final String systemServerPaths = standaloneSystemServerJars != null
                            ? String.join(":", systemServerClasspath, standaloneSystemServerJars)
                            : systemServerClasspath;
                    prepareSystemServerProfile(systemServerPaths);
                    try {
                        SystemProperties.set("debug.tracing.profile_system_server", "1");
                    } catch (RuntimeException e) {
                        Slog.e(TAG, "Failed to set debug.tracing.profile_system_server", e);
                    }
                } catch (Exception e) {
                    Log.wtf(TAG, "Failed to set up system server profile", e);
                }
            }
        }

        // Zygote can't set system properties due to permission denied. We need to be in System
        // Server to set system properties, so we do it here instead of the more natural place in
        // preloadClasses.
        if (shouldProfileBootClasspath()) {
            try {
                SystemProperties.set("debug.tracing.profile_boot_classpath", "1");
            } catch (RuntimeException e) {
                Slog.e(TAG, "Failed to set debug.tracing.profile_boot_classpath", e);
            }
        }

        if (parsedArgs.mInvokeWith != null) {
            String[] args = parsedArgs.mRemainingArgs;
            // If we have a non-null system server class path, we'll have to duplicate the
            // existing arguments and append the classpath to it. ART will handle the classpath
            // correctly when we exec a new process.
            if (systemServerClasspath != null) {
                String[] amendedArgs = new String[args.length + 2];
                amendedArgs[0] = "-cp";
                amendedArgs[1] = systemServerClasspath;
                System.arraycopy(args, 0, amendedArgs, 2, args.length);
                args = amendedArgs;
            }

            WrapperInit.execApplication(parsedArgs.mInvokeWith,
                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);

            throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
        } else {
            ClassLoader cl = getOrCreateSystemServerClassLoader();
            if (cl != null) {
                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl);
        }

        /* should never reach here */
    }

可以看出它们都会先设置 1. 进程的名字

system server 还会额外设置 1. 设置 umask,限制 system_server 创建文件时的默认权限 2. 处理 SYSTEMSERVERCLASSPATH 提前准备自己的 classpath 3. 创建 system_server 使用的 ClassLoader 用于加载 SYSTEMSERVERCLASSPATH 中的 jar 4. 处理 system server / boot classpath profile,用于 profile 采集和启动优化

最后它们都会进入 ZygoteInit.zygoteInit

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
// line 962:989
    /**
     * The main function called when started through the zygote process. This could be unified with
     * main(), if the native code in nativeFinishInit() were rationalized with Zygote startup.<p>
     *
     * Current recognized args:
     * <ul>
     * <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
     * </ul>
     *
     * @param targetSdkVersion target SDK version
     * @param disabledCompatChanges set of disabled compat changes for the process (all others
     *                              are enabled)
     * @param argv             arg strings
     */
    public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }
// ...
// line 1001
    private static native void nativeZygoteInit();

在这里,可以看出先走进了 jni 方法 nativeZygoteInit 通过调用当前 AndroidRuntime 对象的 onZygoteInit()启动了 binder 线程池

/frameworks/base/core/jni/AndroidRuntime.cpp
1
2
3
4
5
// line 275:278
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

调用了当前 AndroidRuntime 对象的 onZygoteInit(),这实际是一个虚函数,在 frameworks/base/cmds/app_process/app_main.cpp 中实现了这个函数:

/frameworks/base/cmds/app_process/app_main.cpp
1
2
3
4
5
6
7
// line 343:344
    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }

执行完后,进入 RuntimeInit.zygoteInit 来启动应用的 main 方法

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
// line 376:395
    protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
                                              String[] argv, ClassLoader classLoader) {
        // If the application calls System.exit(), terminate the process
        // immediately without running any shutdown hooks.  It is not possible to
        // shutdown an Android application gracefully.  Among other things, the
        // Android runtime shutdown hooks close the Binder driver, which can cause
        // leftover running threads to crash before the process actually exits.
        nativeSetExitWithoutCleanup(true);

        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);

        final Arguments args = new Arguments(argv);

        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        // Remaining arguments are passed to the start class's static main
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

zygoteInit 先配置 sdk 等环境,然后调用 findStaticMain

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
// line 308:353
    /**
     * Invokes a static "main(argv[]) method on class "className".
     * Converts various failing exceptions into RuntimeExceptions, with
     * the assumption that they will then cause the VM instance to exit.
     *
     * @param className Fully-qualified class name
     * @param argv Argument vector for main()
     * @param classLoader the classLoader to load {@className} with
     */
    protected static Runnable findStaticMain(String className, String[] argv,
                                             ClassLoader classLoader) {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }

        /*
         * This throw gets caught in ZygoteInit.main(), which responds
         * by invoking the exception's run() method. This arrangement
         * clears up all the stack frames that were required in setting
         * up the process.
         */
        return new MethodAndArgsCaller(m, argv);
    }

通过 ClassLoader 加载目标类,然后反射找到它的 public static main(String[] args)

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
// line 575:606
    /**
     * Helper class which holds a method and arguments and can call them. This is used as part of
     * a trampoline to get rid of the initial process setup stack frames.
     */
    static class MethodAndArgsCaller implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }
    }

这里将目标类的 main 方法保存到 Runnable MethodAndArgsCaller 中了,并且在 run 中能通过 Method.invoke 来调用这个 main 方法

这里的 Runnable 会一直返回到开头的 ZygoteInitmain 中调用 run 方法来启动

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
// line 902:933
            zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }

            Log.i(TAG, "Accepting command socket connections");

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with fatal exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }