基于性能的考虑,Dalvik虚拟机只启动一次,新的实例将从第一次启动的Dalvik中拷贝。这个功能是通过系统服务Zygote来实现的。

Zygote的启动过程简述如下:首先,它预初始化和预加载通用的Android类到它的堆中。然后,它监听在Socket端口上,等待启动一个新的Android应用程序的命令。当接收到一个启动应用程序命令,它将利用已经加载的应用程序fork出一个新的进程。该进程就是被启动的应用程序,且与原始的Zygote进程共享同一个写时复制(copy-on-write)映射的堆。因此,Zygote的堆被链接到该新进程。如果该应用程序只从堆中读取数据,那么就一直与Zygote共享堆。但是,一旦应用程序在堆上执行写操作,那么堆对应的内存页被会被复制且会链接到新页上。这样,应用程序就可以修改过堆中的数据而不用担心会影响Zygote进程的堆了。

当一个新的Android应用程序产生时,它使用Zygote的内存布局,因此,对每个应用程序来说,它们的内存布局是一样的。

下面分析一下代码的流程:

1.  根据init.rc的启动服务的命令,将运行/system/bin/app_process启动zygote。 app_process的命令参数形式为:app_process[java-options] cmd-dir start-class-name [options],

由此可知,传入虚拟机的参数为-Xzygote,首先,-X一般是虚拟机的非标准选项,允许虚拟机定义一些特别的选项,其中zygote就是dalvik虚拟机定义的特制的选项,表示当前运行在zygote模式。在zygote模式下,虚拟机不会启动额外的线程。命令所在的目录是/system/bin,传给app_process的参数是--zygote和--start-system-server。这两个参数表示当前启动的进程名字叫zygote,并且要启动SystemServer。

while (i < argc) {

const char* arg = argv[i++];

if (!parentDir) {

parentDir = arg;

} else if (strcmp(arg, "--zygote") == 0) {

zygote = true;

niceName = "zygote";

} else if (strcmp(arg, "--start-system-server") == 0) {

startSystemServer = true;

} else if (strcmp(arg, "--application") == 0) {

application = true;

} else if (strncmp(arg, "--nice-name=", 12) == 0) {

niceName = arg + 12;

} else {

className = arg;

break;

}

}

2. 接下来,将启动ZygoteInit这个类。在启动这个类之前,会调用startVM(JavaVM** pJavaVM, JNIEnv** pEnv)创建一个dalvik虚拟机,其中JavaVM代表dalvik虚拟机的一个实例,每个进程只有一个实例,JNIEnv代表一个dalvik虚拟机运行环境,每个线程拥有一个实例。接下来通过调用startReg(env)来向虚拟机注册一些JNI本地函数。最后进入ZygoteInit类中的入口函数main中去运行。

if (zygote) {

runtime.start("com.android.internal.os.ZygoteInit",

startSystemServer ? "start-system-server" : "");

} else if (className) {

在Android::start()方法中,启动虚拟机以及注册Android的JNI本地函数。

void AndroidRuntime::start(const char* className, const char* options)

{

...

/* start the virtual machine */

JNIEnv* env;

if (startVm(&mJavaVM, &env) != 0) {

return;

}

onVmCreated(env);

/*

* Register android functions.

*/

if (startReg(env) < 0) {

ALOGE("Unable to register all android natives\n");

return;

}

...

/*

* Start VM.  This thread becomes the main thread of the VM, and will

* not return until the VM exits.

*/

char* slashClassName = toSlashClassName(className);

jclass startClass = env->FindClass(slashClassName);

if (startClass == NULL) {

ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);

/* keep going */

} else {

jmethodID startMeth = env->GetStaticMethodID(startClass, "main",

"([Ljava/lang/String;)V");

if (startMeth == NULL) {

ALOGE("JavaVM unable to find main() in '%s'\n", className);

/* keep going */

} else {

env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0

if (env->ExceptionCheck())

threadExitUncaughtException(env);

#endif

}

}

...

}

3. 接下来,将进入ZygoteInit的main方法,首先registerZygoteSocket()会注册一个服务器端的本地Socket,Socket的路径由环境变量ANDROID_SOCKET_zygote指定。它的主要目的是监听启动应用程序的命令请求,并fork一个子进程来处理启动相应的应用程序。然后,preload()函数会预加载一些资源和一些通用类(由preloaded-classes资源文件指定)。接下来,调用startSystemServer()来启动SystemServer进程。主线程继续执行代码,最后阻塞在runSelectLoop(),在该函数中将接受请求,并fork子进程来处理。

public static void main(String argv[]) {

try {

...

registerZygoteSocket();

...

preload();

...

if (argv[1].equals("start-system-server")) {

startSystemServer();

} else if (!argv[1].equals("")) {

throw new RuntimeException(argv[0] + USAGE_STRING);

}

Log.i(TAG, "Accepting command socket connections");

runSelectLoop();

closeServerSocket();

} catch (MethodAndArgsCaller caller) {

caller.run();

} catch (RuntimeException ex) {

Log.e(TAG, "Zygote died with exception", ex);

closeServerSocket();

throw ex;

}

}

4. 最后我们看一下,如何启动SystemServer。

在startSystemServer()中,进入handleSystemServerProcess(…)。最终调用的是RuntimeInit.zygoteInit(…),这个函数会执行一些通用的初始化,最后通过applicationInit(…)调用com.android.server.SystemServer的main函数。

5. SystemServer会开启一个ServerThread线程,在该线程中启动一系列服务后,最后会通过ActivityManagerService.self().systemReady(…) -> resumeTopActivityLocked->startHomeActivityLocked启动Home Activity,即Launcher。

转载于:https://my.oschina.net/fuyajun1983cn/blog/263817

Zygote启动分析相关推荐

  1. 图解Android - Zygote, System Server 启动分析

    Init 是所有Linux程序的起点,而Zygote于Android,正如它的英文意思,是所有java程序的'孵化池'(玩过星际虫族的兄弟都晓得的).用ps 输出可以看到 >adb shell ...

  2. Zygote启动流程及源码分析

    1 Zygote是什么 在Android中,负责孵化新进程的这个进程叫做Zygote,安卓上其他的应用进程都是由zygote孵化的.众所周知,安卓是Linux内核,安卓系统上运行的一切程序都是放在Da ...

  3. 【Android 性能优化】应用启动优化 ( 安卓应用启动分析 | Launcher 应用启用普通安卓应用 | 应用进程分析 )

    文章目录 一. Launcher 应用 startActivitySafely 方法分析 二. Launcher 中的 startActivity(View v, Intent intent, Obj ...

  4. Android6.0源码分析—— Zygote进程分析(补充)

    原文地址: http://blog.csdn.net/a34140974/article/details/50915307 此博文为<Android5.0源码分析-- Zygote进程分析> ...

  5. Android5.0源码分析—— Zygote进程分析

    1      Zygote简介 Android的应用程序一般都是由Java语言编写而成的,这样的应用程序需要运行在独自的Dalvik虚拟机之上(当然,5.0好像默认了ART了).但是,如果在每一个进程 ...

  6. android6.0源码分析之Zygote进程分析

    在android6.0源码分析之Runtime的初始化一文中,对Zygote进程的初期的Runtime初始化过程进行了分析,在Runtime启动结束后,会对Zygote进程进行初始化,其它Java进程 ...

  7. zygote启动过程

    作者:贾东风 1. zygote是什么? 在 Android 系统中,JavaVM(Java 虚拟机).应用程序进程以及运行系统关键服务的 SystemServer 进程都是由 Zygote 来创建的 ...

  8. Zygote启动及其作用

    目录 1.Zygote简介 2.Zygote进程如何启动 2.1 init.zygote64_32.rc文件 2.2 查看ps信息 2.3 启动 3.Zygote作用 3.1 启动system_ser ...

  9. Android Framework——zygote 启动 SystemServer

    概述 在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,这也许就是为什么要把它称为Zygote(受精卵)的原因吧.由于Zy ...

最新文章

  1. android动态设置错误页面,Android中替换WebView加载网页失败时的页面
  2. const与readonly,析构函数,虚拟方法
  3. 自己动手搭建DNS服务器
  4. neo4jd3的使用流程(转载)
  5. 免费使用的支付宝,到底是怎么一年赚1206亿的?
  6. 分布式定时任务框架Elastic-Job的使用
  7. morse java_华威MORSE,华威数统那个比较好?
  8. iphone label初始化碰到的问题
  9. android中sharedPreferences的用法
  10. R语言分类算法之线性判别分析(Linear Discriminant Analysis)
  11. AndroidStudio_安卓原生开发_在Androidstudio中查看设备管理器---Android原生开发工作笔记160
  12. Android 样式
  13. windows批处理命令大全
  14. UE4/UE5 WebBrowser无法播放直播流的问题
  15. JavaScript 技术篇-如何实现在线logo网站制作后的logo去水印,免费制作无水印logo方法
  16. java 表格_Java创建表格实例详解
  17. vs2019+opencv环境配置
  18. 元宇宙产业委通过央链直播召开第十次新闻通报会:第十一批入会成员名单公布
  19. STM32电子钟万年历Proteus仿真_LCD1602显示
  20. numpy.arange()函数解析

热门文章

  1. buffers和cache的区别
  2. 对使用Jolt调用Tuxedo的一个简单的封装
  3. 程序与生活:程序员要保持好奇心
  4. 2010年7月微软最有价值专家(MVP)当选名单
  5. AMD与intel CPU型号大全(接口)
  6. A 元素[HTML 4.01]
  7. [Gdal-dev] GCP's, Warping and Source Data Projections
  8. 【例题收藏】◇例题·6◇ 电压机制(voltage)
  9. 编写更好的 Java 单元测试的 7 个技巧
  10. JavaCore/HeapDump文件及其分析方法