androidengineers.Book a session

Android Architecture Fundamentals

Zygote & App Spawn Mechanics

article20 minMedium

Every Android app starts as a clone of Zygote — a pre-warmed process that already has the Android framework loaded. Understanding this mechanism reveals why Android apps start in milliseconds instead of seconds.

What Is Zygote?

Zygote is a special process started by init during device boot. It preloads:

  • The ART/Dalvik runtime
  • Common framework classes (Activity, View, Context, etc.)
  • Resources and drawables from the framework
  • OpenGL/Skia libraries

All of this preloading happens once at boot time. When your app starts, it gets a copy of this work for free.

How App Launch Works

init process
    └─ Zygote (preloaded at boot)
           │
           ├─ fork() ──► com.example.myapp
           ├─ fork() ──► com.android.systemui
           └─ fork() ──► com.google.android.gms
  1. User taps your app icon
  2. Launcher asks ActivityManagerService (AMS) to start the Activity
  3. AMS sends a request to Zygote over a Unix socket
  4. Zygote calls fork() — creating a child process with all preloaded state
  5. The child process runs ActivityThread.main(), which calls Application.onCreate() then starts the target Activity

Copy-on-Write: Free Memory Sharing

fork() uses Copy-on-Write (CoW). The child process initially shares all memory pages with Zygote (zero copy cost). Pages are only copied when either process modifies them.

This means:

  • Framework classes loaded by Zygote are shared across ALL app processes
  • A device with 30 apps doesn't have 30 copies of Activity in RAM — just one
  • Your app's unique pages (your classes, your objects) are where memory actually diverges
# See Zygote's preloaded class count
adb shell cat /proc/$(adb shell pidof zygote)/maps | grep ".dex" | wc -l

WebView Zygote

Android maintains a separate WebView Zygote (com.android.webview) that preloads Chromium libraries. WebView rendering runs in an isolated process forked from this Zygote — providing security isolation between web content and your app.

Impact on Cold Start

Cold start time breaks down into:

  1. Fork Zygote (~1–5ms) — fast, OS-level operation
  2. bindApplication (~50–200ms) — JVM setup, your Application class
  3. ContentProvider init — often a hidden bottleneck
  4. Activity creation — inflate layout, bind data
# Measure cold start time
adb shell am force-stop com.example.myapp
adb shell am start-activity -W com.example.myapp/.MainActivity
# Output: TotalTime: 342ms

The Zygote fork itself is not your bottleneck. Your Application.onCreate() and ContentProvider initializations typically are.

Practical Implications

Keep Application.onCreate() fast:

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        // ❌ Don't do heavy init synchronously
        // database.init()   // could take 100ms+
        // sdk.setup()       // often 50-200ms

        // ✅ Use App Startup library for lazy/ordered init
        // Initializers run only when their component is first needed
    }
}

Baseline Profiles accelerate the warm-up phase by pre-compiling your app's hot code paths during install, reducing JIT compilation time on first run.

Key Takeaways

ConceptDetail
ZygotePre-warmed process; avoids re-loading framework on every launch
fork()OS primitive; creates child with all Zygote's state
Copy-on-WriteFramework memory shared until modified — efficient RAM usage
App startAMS → Zygote socket → fork → ActivityThread.main()
Your bottleneckApplication.onCreate(), ContentProviders, not the fork itself

YOUR LEARNING JOURNEY

0 of 177 available lessons completed

Progress saved in this browser. No account needed.
Zygote & App Spawn Mechanics | Android System Design | Android Engineers