了解 Android:Zygote 和 DalvikVM

Posted

技术标签:

【中文标题】了解 Android:Zygote 和 DalvikVM【英文标题】:Understanding Android: Zygote and DalvikVM 【发布时间】:2012-02-27 12:25:54 【问题描述】:

我试图了解 android 如何启动应用程序。问题是 Zygote 如何(以及为什么)分叉一个新的 Dalvik VM?我不明白为什么不能在同一个 Dalvik VM 中运行多个应用程序。

【问题讨论】:

【参考方案1】:

问。 zygote 究竟是如何分叉 Dalvik VM 的?

简答: Zygote 进程在系统启动时冷启动 Java VM。然后它侦听套接字以获取传入命令。每当应用程序需要新进程时,其他进程(例如 ActivityManagerService)将命令写入此套接字。这些命令由 Zygote 进程读取,该进程根据需要调用 fork()。子进程获得一个预热的虚拟机来运行。这就是 Zygote 分叉 Dalvik VM 的方式。

长答案:内核加载后,解析init.rc,启动原生服务。然后运行/system/bin/app_process)。这最终会调用AndroidRuntime.start(),并将参数com.android.internal.os.ZygoteInitstart-system-server 传递给它。

AndroidRuntime.start() 启动一个 Java VM,然后调用ZygoteInit.main(),将参数start-system-server 传递给它。

ZygoteInit.main() 注册 Zygote 套接字(Zygote 进程监听传入的命令,并在收到新命令时根据请求生成一个新进程)。然后它预加载了很多类(如frameworks/base/preloaded-classes 中列出的,在 Android 8.0 中超过 4500 个)和所有系统范围的资源,如可绘制对象、xmls 等。然后它调用startSystemServer(),它为com.android.server.SystemServer 分叉一个新进程.此分叉很特殊,与 Zygote 代表请求进程执行的通常分叉不同。

在 SystemServer 被派生后,runSelectLoopMode() 函数被调用。这是一个while(true) 循环,它与Zygote 套接字建立ZygoteConnection 并等待其上的命令。当收到命令时,会调用ZygoteConnection.runOnce()

ZygoteConnection.runOnce() 然后调用Zygote.forkAndSpecialize(),然后调用本机函数来执行实际的分叉。因此,就像 SystemServer 的情况一样,创建了一个子进程,它为自己继承了一个预热的 Dalvik VM。

问。为什么不能同时运行多个应用程序 达尔维克虚拟机?

据我所知,这是一个设计决策。 Android 人员刚刚决定通过沙盒为每个进程分配一个新的虚拟机以确保安全。

【讨论】:

关于“问。为什么不能在同一个 Dalvik VM 中运行多个应用程序?”当您要求组件与 android:process="" 在同一进程中运行时,是否会发生这种确切的事情这也可以通过使用 android:sharedUserId="" 来完成 "AndroidRuntime.start() 启动 Java VM" 你不是说Dalvik VM吗?【参考方案2】:

没有。 Dalvik 不跨越进程。

但是,Binder IPC 机制可以非常令人信服地使对象看起来迁移到不同的进程及其 Dalvik 实例。此外,内存管理非常适合在所有需要它们的进程之间共享只读页面。托管典型应用程序的 Dalvik 进程是从 zygote 派生的,所有常见的 android 库都已映射,因此不必打开新的唯一副本。

来源:Do apps using multiple processes share a Dalvik instance?

同时检查这些链接:

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

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

【讨论】:

【参考方案3】:

Zygote 还用于与所有应用程序共享系统绘图。 这允许系统只加载一次按钮的位图 实例。

【讨论】:

这对双方都有好处:Zygote 加载了 OpenSSL 的低级版本。期望加载 its 版本的 OpenSSL 的应用程序通常会卡在低级版本,因为 Zygote 在分叉之前已经加载了它。这包括支持 FIPS 的 OpenSSL 版本,应用程序正在尝试使用经过验证的加密。【参考方案4】:

当 zygote 在接收到它使用 copy-on-write 技术的命令时执行分叉时,只是为了在上面的答案中再添加一点。仅当新进程尝试修改内存时才会复制内存。

此外,zygote 在启动时加载的核心库只读,无法修改。因此,它们不会被复制,而是与新的分叉进程共享

所有这些都导致快速启动更少的内存占用

【讨论】:

【参考方案5】:

Zygote 并没有真正与 Dalvik 绑定,它只是一个 init 进程。 Zygote 是 Android 用来启动应用程序的方法。不必从头开始每个新进程,每次要启动应用程序时都重新加载整个系统和 Android 框架,它会执行一次该过程,然后在 Zygote 执行任何特定于应用程序的操作之前停止.然后,当您要启动应用程序时,Zygote 进程会分叉,子进程会从中断处继续,将应用程序本身加载到 VM 中。

【讨论】:

以上是关于了解 Android:Zygote 和 DalvikVM的主要内容,如果未能解决你的问题,请参考以下文章

小米Android岗二面:面试官让我说说对Zygote的理解!

Android Zygote启动流程源码解析

Android Zygote介绍

Android-深入理解zygote

Android 世界中,谁喊醒了 Zygote ?

Android学习之zygote启动流程