SoFunction
Updated on 2025-03-02

Detailed explanation of the Android FrameWork Zygote startup example

1. Introduction to Zygote

Zygote is a process. After the boot kernel is started, the first process in the user space, the Init process, is started, and then the Init process will start the Zygote process.

As an incubator, the Zygote process is mainly used to fork new processes, such as the SystemServer process used for system services, our APP process, etc.

When Zygote starts, it will create and start our Java virtual machine, and the processes produced by Zygote through fork will also have the same functions as the parent process, which will also have our Java virtual machine environment.

So this is why each process in the Android system has a virtual machine, except for non-Zygote fork processes.

2. Zygote's startup script

Script path: system/core/rootdir/init.

Script content:

    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

As can be seen from the first line of the script, the process of Zygote is named zygote, the executor is app_process, and the class name is main. We go to find the corresponding app_process.

Path: frameworks/base/cmds/app_process

There is a file for app_main.cpp under the path of app_process:

frameworks/base/cmds/app_process/app_main.cpp

From this we can guess that this can be used as the code entry for the zygote process to start.

3. App_process app_main.cpp source code analysis

frameworks/base/cmds/app_process/app_main.cpp

We found the app_main.cpp its main function

int main(int argc, char* const argv[])
{
    ....
   // 1. Created the AppRuntime object    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;
    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;
    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            (arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            (arg);
            break;
        } else {
            --i;
            break;
        }
    }
 ......
 ......
    if (zygote) {
      //2. Call the start function of runtime        ("", args, zygote);
    } else if (className) {
        ("", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

The core function of the main function is to create the AppRuntime runtime object and call the start method. The className parameter passed here is (full class name)
AppRuntime inherits AndroidRuntime. Let's look at the start function in AndroidRuntime.

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ....
   ....
   ....
    /* start the virtual machine 3. Start the Java virtual machine*/
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);
    .....
   /*
      * Register android functions.
       *Register android native functions with the VM.
      * 4. Register android local functions with the virtual machine.
      */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
  .....
   .....
.....
    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
        //5. Use the env object and call the main function of the startClass class through JNI.        //The startClass class was passed on before        //
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
    }

The above process is mainly:

  • Create an AppRuntime object and call its start function.
  • First call the startVm function in the start function to start the Java virtual machine
  • After starting the Java virtual machine, call the startReg function and register the JNI
  • Calling the main function of ZygoteInit class through JNI
    Then I entered the Java world from Native

4. Source code analysis

frameworks/base/core/java/com/android/internal/os/

public static void main(String argv[]) {
      //1. Create a ZygoteServer object        ZygoteServer zygoteServer = new ZygoteServer();
        final Runnable caller;
        try {
            ....
            ....
            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < ; 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]);
                }
            }
           //2. Register a local ServerSocket named "zygote"            (socketName);
                if (!enableLazyPreload) {
                ("ZygotePreload");
                (LOG_BOOT_PROGRESS_PRELOAD_START,
                    ());
              //Preload executes preload, and it is mainly called in the preload function              //preloadClasses and preloadResources(); load some system resources and system classes,                preload(bootTimingsTraceLog);
                (LOG_BOOT_PROGRESS_PRELOAD_END,
                    ());
                (); // ZygotePreload
            } else {
                ();
            }
            if (startSystemServer) {
              //Calling the fork function, start the creation and startup of the SystemServer process                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
              //This sentence is very important. If it is zygote in the parent process, it will return null. If it is in the system_server process, it will not be null.              //So when the zygote process is not satisfied                if (r != null) {
                    ();
                    return;
                }
            }
            (TAG, "Accepting command socket connections");
            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
          //In the zygote process, call runSelectLoop to enter the wireless loop. If it is a child process, return the caller object.            caller = (abiList);
        } catch (Throwable ex) {
            (TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
          //If it is not in the zygote process, exit the loop and enter here, close the socket server            ();
        }
        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
      //If it is in a child process, call the caller run function through the returned caller object.        if (caller != null) {
            ();
        }
    }

The main function of ZygoteInit is mainly done as follows:

  • Create and register a local SocketServer named "zygote", that is, the Zygote process is used as the server of LocalSocket
  • Calling preloadClasses and preloadResources functions in preload function preloads system classes and some system resources
  • Call forkSystemServer to create a startup SystemServer process and return a Runnable r object. At this time, the Zygote and SystemServer processes are running, and they execute different code branches respectively without passing the process.
  • If it is in the SystemServer process, the function will be executed directly and return. If it is in the Zygote process, it will go down, and the runSelectLoop function in the zygoteServer is called, entering an infinite loop. The comment also describes that if it is in other child processes, the loop will exit and return a Runnable caller object. And go down and call the function.

5. Summary

The Zygote process started mainly to do the following work
Native layer

  • Create a startup Java virtual machine
  • Register for JNI
  • Main function called via JNI
    Java layer
  • Create and register a local SocketServer named "zygote" for communication between processes. The Zygote process is used as a server. In fact, the purpose of the Zygote process is to communicate with the subsequent SystemServer process.
  • Preload some classes and resources
  • fork child process SystemServer
  • runSelectLoop enters wireless loop

The above is the detailed explanation of the detailed explanation of the Android FrameWork Zygote startup example. For more information about Android FrameWork Zygote startup, please follow my other related articles!