美文网首页
Android应用启动的本质(一)

Android应用启动的本质(一)

作者: 榕城歌者 | 来源:发表于2019-06-23 11:31 被阅读0次

    概述

    从framework层认识应用启动的过程,了解应用启动、切换过程背后的实质,本文以Launcher为切入点。

    Launcher

    Android用户第一个接触到应用之间的切换,就是从Launcher到其它任意的应用程序。Launcher也是一个由多个Activity构成的程序,与其它应用没有本质上的差别。它的特殊之处,在于它是Android系统启动的第一个应用程序,也是所有返回操作(按Home键)的最终页面,同时它也展示已安装的应用。

    比Launcher更早启动的应用程序

    答案是有,有许多的服务在系统启动过程被启动了。
    init进程是Android系统中用户空间的第一个进程,作为第一个进程,它被赋予了很多极其重要的工作职责,比如创建Zygote和属性服务等。应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程来创建的,我们也将它称为孵化器。

    Zygote

    应用之间的切换,一个应用转入后台,同时也伴随着一个应用的启动。启动过程调用了大量的系统服务,而这些系统服务都是已经提前启动了,在Zygote初始化方法中启动的。

    所以要先讲述一下Zygote的启动流程,以及他启动过程都干了什么操作。

    1、Zygote启动流程

    init启动zygote时主要是调用app_main.cpp的main函数中的AppRuntime的start来启动zygote进程。
    源码文件:frameworks/base/cmds/app_process/app_main.cpp

    int main(int argc, char* const argv[])
    {
    ...
    
        AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
       ...
    
        if (zygote) {
            runtime.start("com.android.internal.os.ZygoteInit", args, zygote);//1
        } 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.");
            return 10;
        }
    }
    

    注释1处这里调用runtime的start函数来启动zygote进程,并将args传入,这样启动zygote进程后,zygote进程会将SystemServer进程启动。我们知道runtime指的就是AppRuntime,AppRuntime声明也在app_main.cpp中,它继承AndroidRuntime,也就是我们调用start其实是调用AndroidRuntime的start函数:
    源码文件:frameworks/base/core/jni/AndroidRuntime.cpp

    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
        ...
        /* start the virtual machine */
        JniInvocation jni_invocation;
        jni_invocation.Init(NULL);
        JNIEnv* env;
        if (startVm(&mJavaVM, &env, zygote) != 0) {//1
            return;
        }
        onVmCreated(env);
        if (startReg(env) < 0) {//2
            ALOGE("Unable to register all android natives\n");
            return;
        }
        jclass stringClass;
        jobjectArray strArray;
        jstring classNameStr;
    
        stringClass = env->FindClass("java/lang/String");
        assert(stringClass != NULL);
        //创建数组
        strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
        assert(strArray != NULL);
        //从app_main的main函数得知className为com.android.internal.os.ZygoteInit
        classNameStr = env->NewStringUTF(className);
        assert(classNameStr != NULL);
        env->SetObjectArrayElement(strArray, 0, classNameStr);
    
        for (size_t i = 0; i < options.size(); ++i) {
            jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
            assert(optionsStr != NULL);
            env->SetObjectArrayElement(strArray, i + 1, optionsStr);
        }
        char* slashClassName = toSlashClassName(className);
        jclass startClass = env->FindClass(slashClassName);
        if (startClass == NULL) {
            ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
            /* keep going */
        } else {
        //找到ZygoteInit的main函数
            jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
                "([Ljava/lang/String;)V");//3
            if (startMeth == NULL) {
                ALOGE("JavaVM unable to find main() in '%s'\n", className);
                /* keep going */
            } else {
            //通过JNI调用ZygoteInit的main函数
                env->CallStaticVoidMethod(startClass, startMeth, strArray);//4
    
    #if 0
                if (env->ExceptionCheck())
                    threadExitUncaughtException(env);
    #endif
            }
        }
      ...
    }
    

    注释1处调用startVm函数来创建JavaVm(DVM)
    注释2处调用startReg函数用来为DVM注册JNI。
    注释3处的代码用来找到ZygoteInit的main函数,其中startClass从app_main的main函数得知为com.android.internal.os.ZygoteInit。
    注释4处通过JNI调用ZygoteInit的main函数,因为ZygoteInit的main函数是Java编写的,因此需要通过JNI调用。
    ZygoteInit的main函数后,Zygote便进入了Java框架层,在此之前没有任何Java代码被调用,这是第一个执行Java文件。

    public static void main(String argv[]) {
          ...
           try {
            ...       
               //注册Zygote用的Socket
               registerZygoteSocket(socketName);//1
              ...
              //预加载类和资源
              preload();//2
              ...
               if (startSystemServer) {
               //启动SystemServer进程
                   startSystemServer(abiList, socketName);//3
               }
               Log.i(TAG, "Accepting command socket connections");
               //等待客户端请求
               runSelectLoop(abiList);//4
               closeServerSocket();
           } catch (MethodAndArgsCaller caller) {
               caller.run();
           } catch (RuntimeException ex) {
               Log.e(TAG, "Zygote died with exception", ex);
               closeServerSocket();
               throw ex;
           }
       }
    

    Zygote做了四件特别重要的事情:
    注释1处通过registerZygoteSocket函数来创建一个Server端的Socket,这个name为”zygote”的Socket用来等待ActivityManagerService来请求Zygote来创建新的应用程序进程。
    这就是应用启动(冷启动)的实质操作,所有的应用启动以及Activity之间的切换都是通过ActivityManagerService来调度的。具体操作,后面细说。
    注释2处用来预加载类和资源。
    注释3处用来启动SystemServer进程,这样系统的关键服务也会由SystemServer进程启动起来。
    注释4处调用runSelectLoop函数来等待客户端请求

    2、总结

    1.创建AppRuntime并调用其start方法,启动Zygote进程。
    2.创建DVM并为DVM注册JNI.
    3.通过JNI调用ZygoteInit的main函数进入Zygote的Java框架层。
    4.通过registerZygoteSocket函数创建服务端Socket,并通过runSelectLoop函数等待ActivityManagerService的请求来创建新的应用程序进程。
    5.启动SystemServer进程。

    Zygote通过fork(复制进程)的形式来创建应用程序进程和SystemServer进程,由于Zygote进程在启动时会创建DVM,因此通过fork而创建的应用程序进程和SystemServer进程可以在内部获取一个DVM的实例拷贝。
    除了创建新的应用程序进程,我们要注意的是这个SystemServer进程。

    SystemServer干了什么?

    启动了大量的服务。
    源码文件frameworks/base/services/java/com/android/server/SystemServer.java

    private void run() {
           ...
               System.loadLibrary("android_servers");//1
           ...
               mSystemServiceManager = new SystemServiceManager(mSystemContext);//2
               LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
           ...    
            try {
               Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
               startBootstrapServices();//3
               startCoreServices();//4
               startOtherServices();//5
           } catch (Throwable ex) {
               Slog.e("System", "******************************************");
               Slog.e("System", "************ Failure starting system services", ex);
               throw ex;
           } finally {
               Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
           }
           ...
       }
    

    注释2处创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理。
    注释3启动系统的各种服务,startBootstrapServices函数中用SystemServiceManager启动了ActivityManagerService、PowerManagerService、PackageManagerService等服务。
    在注释4处的函数中则启动了BatteryService、UsageStatsService和WebViewUpdateService。
    注释5处的startOtherServices函数中则启动了CameraService、AlarmManagerService、VrManagerService等服务,这些服务的父类为SystemService。
    官方把系统服务分为了三种类型,分别是引导服务、核心服务和其他服务,其中其他服务为一些非紧要和一些不需要立即启动的服务。

    相关文章

      网友评论

          本文标题:Android应用启动的本质(一)

          本文链接:https://www.haomeiwen.com/subject/hslyqctx.html