了解 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.ZygoteInit
和start-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="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的主要内容,如果未能解决你的问题,请参考以下文章