Android P zygote 原理分析之app_process

  • Post author:
  • Post category:其他


Android系统内核初始化完毕后,进入用户空间启动的第一个进程叫init 他是Android系统所有进程的祖先,这个进程启动后会初始化文件系统,然后养育很多娃,比如系统中许许多多的服务,其中有一个服务名字就叫zygote ,zygote 翻译过来其实就叫做受精卵,它应该是init的所有娃中比较特殊的一个,其他的娃多大是一些底层服务,而zygote 这个娃的特殊之处在于它负责启动java虚拟机,并将android带入java的世界中,从此android与众不同,我想这也是android在技术上与其他众多类linux系统的主要差别之一吧!

zygote 在android中具有重要的作用,那么到底有什么用呢??

1.负责启动java虚拟机

2.加载很多需要预加载的类

3.负责启动systemServer ,systemServer 会启动android中的所有服务,基本上完成了上层框架的所有功能。

4.负责初始化新进程,其实就是fork java的独立进程,比如启动一个act,那么zygote 就负责为新启动的act 建立进程,并调用act中的main,或者OnCreate,这样或许大家更容易理解。

但是对于init来说zygote其实就是一个很普通的服务,与他养育的其他娃没有任何差别。请看代码:

service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks

因为对于处理器平台来说有32 和64位的差别,我们手里的手机也有这个差别,所有zygote 也是有这个差别的,其实它分为32,64,32_64,64_32,这四种模式,或许有一天会有128,512模式。以上代码就是32_64位模式,主模式是32位,辅助模式是64位,其实这个手机是64位的,但是他支持32位,而这种设置会将大多数应用以32模式运行,但是一些具有特殊要求的应用也会以64位模式运行,这是负责创建进程的将是zygote_secondary。

下面我们来分析一下app_process 这个进程:

app_process 这个进程不仅能启动zygote 而且也是可以启动一个普通的类的,他会根据你参数的不同来实现不同的功能。

-Xzygote 这个参数是传给虚拟机的,并不是传给app_process 的,表示需要重新初始化一个新的jvm

–zygote: 这个参数传给app_process 表示启动zygote 模式。

–start-system-server:这个参数表示启动systemServer 服务。一般情况下,这个参数只有zygote 模式才有,因为其他模式貌似不需要这个东西。

–socket-name=zygote:这个参数表示socket 的名称,因为zygote 启动完毕后,并不会退出,他还负责为其他应用创建进程,ams就是通过这个socket与zygote 通讯来完成进程创建的。

–application:这个其实是另外一种模式的标志,表示启动的为普通应用,

–nice-name=  这个表示创建的进程的名字,zygote 模式没有这个东西。

-classpath 或者-cp  这个为创建普通应用时的class路径,我猜的。

app_process 的main函数主要是对于以上的参数的处理,除了这个之外就是新建APPRuntime类

AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

这个类负责启动java的main class

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }

负责初始化zygote 模式的叫ZytoteInit 类,负责初始化其他进程的叫RuntimeInit 类。

其实如果要继续分析的话,则可以沿着这两条线,继续去分析,我想后面会有奇迹等着你哦!

不过我们今天的任务是分析app_process ,另外的交给未来吧!

如果要明白,app_process 如何启动jvm ,如何跳转java层,那么不分析AppRuntime 则是不现实的,估计也就变成徒有其表了。现在我们来分析今天唯一有点难度的AppRuntime

AppRuntime 继承AndroidRuntime ,因为AndroidRuntime 有两个虚函数所以,AppRuntime 主要实现这个两个函数:


    /**
     * This gets called after the VM has been created, but before we
     * run any code. Override it to make any FindClass calls that need
     * to use CLASSPATH.
     */
    virtual void onVmCreated(JNIEnv* env);

    /**
     * This gets called after the JavaVM has initialized.  Override it
     * with the system's native entry point.
     */
    virtual void onStarted() = 0;
    /**
     * This gets called after the JavaVM has initialized after a Zygote
     * fork. Override it to initialize threads, etc. Upon return, the
     * correct static main will be invoked.
     */
    virtual void onZygoteInit() { }

    /**
     * Called when the Java application exits to perform additional cleanup actions
     * before the process is terminated.
     */
    virtual void onExit(int /*code*/) { }

从名字我们就应该可以看出来,一个为虚拟机创建完毕后调用,一个为虚拟机启动完毕后调用。

对于AppRuntime 来说,onVmCreated 主要作用是设置主函数名称,onStarted函数为启动事件管理器,并且调用main函数。

对于zygote 模式来说,onVmCreated 无效。

下面我们来看看最重要的那个函数,runtime.start 函数,这个函数主要完成以下任务:

1.初始化jni

2.启动jvm虚拟机

3.注册无数的jni函数

4.启动java类

初始化jni:

主要调用jni_invocation.Init 完成初始化

  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
                  "JNI_GetDefaultJavaVMInitArgs")) {
    return false;
  }
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
                  "JNI_CreateJavaVM")) {
    return false;
  }
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
                  "JNI_GetCreatedJavaVMs")) {
    return false;
  }

其实主要转换这几个jni函数,这几个jni函数会在创建虚拟机的时候被调用

创建虚拟机主要涉及无数的参数处理,最后调用

JNI_CreateJavaVM

完成jvm的创建。

注册jni无数上层java需要调用的jni函数,其实这里负责调用各个jni注册函数。我猜测应该包含了系统初始化阶段所有的jni函数。

调用java类的静态main函数的方法就很通用了。貌似没什么特别的。



版权声明:本文为haozhenghui10原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。