ZygoteSource

原理图

sequenceDiagram 

ZygoteProcess->>ZygoteProcess: ZygoteInit.main
activate ZygoteProcess

ZygoteProcess->>SystemServerProcess: forkSystemServer
activate SystemServerProcess
SystemServerProcess->>SystemServerProcess: handleSystemServerProcess
activate SystemServerProcess
SystemServerProcess->>SystemServerProcess: ZygoteInit.zygoteInit
deactivate SystemServerProcess
activate SystemServerProcess
SystemServerProcess->>SystemServerProcess: SystemServer.main
deactivate SystemServerProcess
deactivate SystemServerProcess

activate ZygoteProcess
ZygoteProcess->>ZygoteProcess: runSelectLoop

SystemServerProcess->>ZygoteProcess: notify

activate ZygoteProcess
ZygoteProcess->>ZygoteProcess: processOneCommand

ZygoteProcess->>ChildAppProcess: Zygote.forkAndSpecialize
deactivate ZygoteProcess


activate ChildAppProcess
ChildAppProcess->>ChildAppProcess: handleChildProc
activate ChildAppProcess

ChildAppProcess->>ChildAppProcess: ZygoteInit.zygoteInit
deactivate ChildAppProcess
activate ChildAppProcess

ChildAppProcess->>ChildAppProcess: ActivityThead.main
deactivate ChildAppProcess
deactivate ChildAppProcess

deactivate ZygoteProcess
deactivate ZygoteProcess

ZygoteInit.main

    public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();
           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)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }
        
        zygoteServer.registerServerSocketFromEnv(socketName);
        
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, 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);
            // We're in the child process and have exited the select loop. Proceed to execute the
            // command.
       		  if (caller != null) {
                caller.run();
            }
    }

forkSystemServer

    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.runtimeFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        
                /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }
       
   /** @return 0 if this is the child, pid of the child
     * if this is the parent, or -1 on error.
      */
public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        // Enable tracing as soon as we enter the system_server.
        if (pid == 0) {
            Trace.setTracingEnabled(true, runtimeFlags);
        }
     return pid;
}

SystemServer

handleSystemServerProcess

/**
 * Finish remaining work for the newly forked system server process.
 */
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}

zygoteInit

    public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }
RuntimeInit.commonInit
@UnsupportedAppUsage
protected static final void commonInit() {
    /*
     * set handlers; these apply to all threads in the VM. Apps can replace
     * the default handler, but not the pre handler.
     */
    LoggingHandler loggingHandler = new LoggingHandler();
    RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler);
    Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));
}

frameworks/base/core/jni/AndroidRuntime.cpp

nativeZygoteInit
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

frameworks/base/cmds/app_process/app_main.cpp

    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }
RuntimeInit.applicationInit
    protected static Runnable applicationInit(int targetSdkVersion, 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);

        // We want to be fairly aggressive about heap utilization, to avoid
        // holding on to a lot of memory that isn't needed.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

        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);
    }
//ActivityThread的全类名由AMS startProcess时写入到socket,zygoteServer再读取,传递过来    
protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        cl = Class.forName(className, true, classLoader);
        
        
        Method m;
         m = cl.getMethod("main", new Class[] { String[].class });
         return new MethodAndArgsCaller(m, argv);

ZygoteServer

runSelectLoop

    /**
     * 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.
     */
    Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

        fds.add(mServerSocket.getFileDescriptor());
        peers.add(null);
        
        while (true) {
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            for (int i = 0; i < pollFds.length; ++i) {
                pollFds[i] = new StructPollfd();
                pollFds[i].fd = fds.get(i);
                pollFds[i].events = (short) POLLIN;
            }
            try {
                Os.poll(pollFds, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            
           for (int i = pollFds.length - 1; i >= 0; --i) {
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
                if (i == 0) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    try {
                        ZygoteConnection connection = peers.get(i);
                        final Runnable command = connection.processOneCommand(this);
                    }
                }
           }
        }

ZygoteConnection.processOneCommand

    /**
     * Reads one start command from the command socket. If successful, a child is forked and 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).
     */
 Runnable processOneCommand(ZygoteServer zygoteServer) {
          args = readArgumentList();//读取socket数据,解析启动参数
          parsedArgs = new Arguments(args);
   
          pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
                parsedArgs.instructionSet, parsedArgs.appDataDir);
     
           if (pid == 0) {
                // in child
                zygoteServer.setForkChild();

                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;

                return handleChildProc(parsedArgs, descriptors, childPipeFd,
                        parsedArgs.startChildZygote);
            } else {
                // In the parent. A pid < 0 indicates a failure and will be handled in
                // handleParentProc.
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                handleParentProc(pid, descriptors, serverPipeFd);
                return null;
            }

ChildProcess

handleChildProc

   private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
            FileDescriptor pipeFd, boolean isZygote) {
       
          if (!isZygote) {
                return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
                        null /* classLoader */);
            } else {
                return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
                        parsedArgs.remainingArgs, null /* classLoader */);
            }
      

zygoteInit

zygoteinit

参考

«深入理解Android 卷1 4.4.1ActivityManagerService发送请求>

Zygote为什么使用Socket不用Binder

fork()不支持多线程,如果使用Binder则fork()时可能会丢弃binder线程池中的任务或造成死锁,而通过socket进行单线程可以解决这个问题

安全性?

RuntimeInit.main //没啥机会调用到

@UnsupportedAppUsage
public static final void main(String[] argv) {
    enableDdms();

    commonInit();

    /*
     * Now that we're running in interpreted code, call back into native code
     * to run the system.
     */
    nativeFinishInit();
}