62

I am trying to understand how Android launches applications. The question is how (and why) does the Zygote fork a new Dalvik VM? I do not understand why it is not possible to run multiple applications in the same Dalvik VM.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
Aprel
  • 1,089
  • 2
  • 14
  • 25

5 Answers5

168

Q. how does zygote exactly fork Dalvik VM?

Short Answer: The Zygote process cold boots a Java VM on system start up. It then listens to a socket for incoming commands. Other processes (e.g. ActivityManagerService) write commands to this socket whenever a new process is needed for an application. These commands are read by the Zygote process which calls fork() as necessary. Child processes get a pre-warmed VM in which to run. This is how Zygote forks the Dalvik VM.

Long answer: After the kernel is loaded, init.rc is parsed and native services are started. Then /system/bin/app_process) is run. This eventually calls AndroidRuntime.start(), passing it the parameters com.android.internal.os.ZygoteInit and start-system-server.

The AndroidRuntime.start() starts a Java VM then calls ZygoteInit.main(), passing it the parameter start-system-server.

ZygoteInit.main() registers the Zygote socket (which the Zygote process listens to for incoming commands, and on receiving new command, spawns a new process as requested). It then preloads a lot of classes (as listed in frameworks/base/preloaded-classes, over 4500 in Android 8.0) and all the system-wide resources like drawables, xmls, etc. Then it calls startSystemServer() which forks a new process for com.android.server.SystemServer. This fork is special and is not done in the same manner as the usual forks the Zygote performs on behalf of requesting processes.

After SystemServer is forked the runSelectLoopMode() function is called. This is a while(true) loop which establishes a ZygoteConnection with the Zygote socket and waits for commands on it. When a command is received, ZygoteConnection.runOnce() is called.

ZygoteConnection.runOnce() then calls Zygote.forkAndSpecialize() which then calls a native function to do the actual fork. Thus, like in the case of SystemServer, a child process is created which inherits a pre-warmed Dalvik VM for itself.

Q. why it is not possible to run multiple applications in the same Dalvik VM?

This is a design decision as far as I know. The Android guys just decided to fork a new VM per process for security via sandboxing.

Allen Luce
  • 7,859
  • 3
  • 40
  • 53
Aswin Kumar
  • 5,158
  • 5
  • 34
  • 39
  • About "Q. why it is not possible to run multiple applications in the same Dalvik VM?" Dosn't this exact thing happen when you ask for components to run in a same process with android:process="" Also this can be done by using android:sharedUserId="" – Igor Čordaš Jun 16 '15 at 12:13
  • "AndroidRuntime.start() starts the Java VM" didn't you mean `Dalvik VM`? – PcAF Mar 04 '17 at 23:53
35

No. Dalvik doesn't span processes.

However, the Binder IPC mechanism can do a very convincing job of making objects appear to migrate to a different process and its Dalvik instance. Also, the memory management is very good about sharing read-only pages across all processes that need them. The Dalvik process hosting a typical app is forked off of zygote with all the common android libraries already mapped, so new unique copies don't have to be opened.

Source: Do apps using multiple processes share a Dalvik instance?

Also check these links:

http://davidehringer.com/software/android/The_Dalvik_Virtual_Machine.pdf

http://commonsware.com/blog/Articles/what-is-dalvik.html

Community
  • 1
  • 1
Paul
  • 5,163
  • 3
  • 35
  • 43
6

Zygote is also used to share the system drawables with all the apps. This allows the system to load the bitmaps for buttons only once for instance.

Basimalla Sebastin
  • 1,159
  • 3
  • 9
  • 15
  • 1
    That cuts both ways: Zygote loads a down level version of OpenSSL. An app that expects to load *its* version of OpenSSL is often stuck with the down level version because Zygote already loaded it before the fork. That includes FIPS Capable versions of OpenSSL, where the app is trying to use validated cryptography. – jww May 26 '15 at 22:52
5

Just to add one more point to answers above when zygote does a fork on receiving a command it uses copy-on-write technique. Memory is copied only when the new process tries to modify it.

Also the core libraries that zygote loads on startup are read only and cannot be modified. So they are not copied over but shared with new forked processes.

All of these led to quick startup and less memory footprint.

Aniket Thakur
  • 66,731
  • 38
  • 279
  • 289
4

Zygote isn't really bound up with Dalvik, it's just an init process. Zygote is the method Android uses to start apps. Rather than having to start each new process from scratch, loading the whole system and the Android framework afresh each time you want to start an app, it does that process once, and then stops at that point, before Zygote has done anything app-specific. Then, when you want to start an app, the Zygote process forks, and the child process continues where it left off, loading the app itself into the VM.

M_ Fa
  • 487
  • 10
  • 11