333 – Android Zygote: The Incubator for All App Processes
Series Navigation: 330-Boot Overview | 331-Bootloader | 332-init Process
In the previous article, we covered the init process — the first userspace process, responsible for parsing configuration, mounting filesystems, managing properties, and starting key services. The most important of these services is Zygote.
Zygote is one of Android’s most unique designs. It is the parent process of all Java application processes. Through preloading class libraries and a fork model, it achieves remarkable application startup speed optimization.
Understanding Zygote is the key to understanding the overall Android architecture.
What Is Zygote
Zygote (fertilized egg) — the name itself hints at its role: it is the “matrix” of all processes in the Android system.
From a process relationship perspective:
init (PID 1)
└── zygote (PID 1's child process)
├── system_server (forked from zygote)
└── com.example.myapp (forked from zygote, 100+ app processes)From a technical standpoint, Zygote is a Java process that, at startup:
- Preloads all Java core class libraries (android.jar + framework.jar)
- Pre-creates a virtual machine instance (but doesn’t start the app’s main yet)
- Starts a ServerSocket, waiting for AMS requests
- Upon receiving a fork request, copies itself via the
fork()system call
Zygote process (all class libraries and resources already loaded)
│
│ AMS requests fork of a new app process
▼
fork() ─────────────────────────────────────────┐
│ │
▼ ▼
Child process (APP) Parent process (continues listening)
· Copies parent's address space
· Inherits all loaded classes
· Executes Application.onCreate()
· Starts ActivityThread.main()Key point: Because classes are already loaded in Zygote, the child process does not need to reload classes, saving several seconds of cold start time.
Why Is Zygote Needed
Android introduced Zygote in the Dalvik era, mainly to solve two problems:
Problem 1: Every process must load all classes → Slow
In a design without Zygote, every app process would need to:
App process startup
→ Create a Dalvik/ART virtual machine instance (~20-50MB memory allocation)
→ Load java.*, javax.*, android.*, dalvik.*, ...
→ Link native libraries (JNI)
→ Execute Application.onCreate()
→ Start the four componentsThis would cause:
- Slow first startup: Thousands of classes reloaded each time
- Memory waste: Each process has its own copy of class data (.dex cache)
Problem 2: Native library initialization overhead
When JNI calls native code, it needs System.loadLibrary(). If every app loads the same set of shared libraries, there would be multiple copies in memory.
┌────────────────┬────────────────┐
│ Zygote (shared)│ APP1 process │
│ libandroid.so │ - │ ← Already loaded by Zygote, shared after fork
│ libicu*.so │ - │
└────────────────┴────────────────┘
Copy-on-Write (CoW):
After fork, child process shares Zygote's address space
Only when the child writes to a page does it get its own copy
Most class data is read-only → truly sharedZygote Startup Process
Zygote startup process:
1. init starts zygote via init.rc:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
2. app_process is a C++ executable that invokes:
frameworks/base/core/jni/AndroidRuntime.cpp
3. AndroidRuntime::start():
- Starts the Java VM (Dalvik or ART)
- Calls ZygoteInit.main() via JNI
4. ZygoteInit.main():
- registerZygoteSocket(): Creates a ServerSocket to listen for AMS connections
- preload(): Preloads all classes, resources, and shared libraries
- startSystemServer(): Forks the SystemServer process
- runSelectLoop(): Enters the main loop, waiting for AMS fork requestsZygote preload content:
1. Java classes (~2000+):
- All public classes in android.jar
- Framework service classes (partially)
- Common UI classes (View, Activity, etc.)
- Core library classes (java.lang.*, java.util.*, etc.)
2. Resources:
- android.R.*** (all system resources)
- Common themes, colors, layouts
3. Native libraries:
- libandroid.so, libicu*.so, libsqlite.so, ...
- Graphics libraries (libEGL*, libGLES*, libvulkan*)
- Media libraries (libstagefright*, libmedia*)
4. Pre-compiled (when using ART):
- .oat files (pre-compiled dex bytecode to machine code)
Comments