首頁 > 軟體

Android10 啟動Zygote原始碼解析

2022-10-12 14:01:54

app_main

上一篇文章:

# Android 10 啟動分析之servicemanager篇 (二)

在init篇中有提到,init程序會在在Trigger 為late-init的Action中,啟動Zygote服務,這篇文章我們就來具體分析一下Zygote服務,去挖掘一下Zygote負責的工作。

Zygote服務的啟動入口原始碼位於 /frameworks/base/cmds/app_process/app_main.cpp,我們將從這個檔案的main方法開始解析。

int main(int argc, char* const argv[])
{
    //宣告AppRuntime類的範例runtime,在AppRuntime類的構造方法中初始化的skia圖形引擎
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ...
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;
    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            //對於64位元系統nice_name為zygote64; 32位元系統為zygote
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            //是否需要啟動system server
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            //啟動進入獨立的程式模式
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
               //niceName 為當前程序別名,區別abi型號
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }
    ...
}

可以看到,app_main根據啟動時傳入引數的區別,分為zygote 模式和application模式。

我們可以從init.zygote64_32.rc檔案中看到zygote的啟動引數為:

-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote

我們接著往下看:

Vector<String8> args;
    if (!className.isEmpty()) {
        // We're not in zygote mode, the only argument we need to pass
        // to RuntimeInit is the application argument.
        //
        // The Remainder of args get passed to startup class main(). Make
        // copies of them before we overwrite them with the process name.
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
        if (!LOG_NDEBUG) {
          String8 restOfArgs;
          char* const* argv_new = argv + i;
          int argc_new = argc - i;
          for (int k = 0; k < argc_new; ++k) {
            restOfArgs.append(""");
            restOfArgs.append(argv_new[k]);
            restOfArgs.append("" ");
          }
          ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
        }
    } else {
        // We're in zygote mode.
        //初始化Dalvik虛擬機器器Cache目錄和許可權
        maybeCreateDalvikCache();
        if (startSystemServer) {
           //附加上start-system-serve 的arg
            args.add(String8("start-system-serve 的argr"));
        }
        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }
        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);
        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }
    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.");
    }

結合傳入的啟動引數來看,程式碼將從if語句的else分支繼續往下執行,進入zygote模式。至於application模式我們暫時先忽略它,等我們分析app的啟動過程時再來說明。

上述程式碼最後將通過 runtime.start("com.android.internal.os.ZygoteInit", args, zygote);語句,將控制許可權轉交給AppRuntime類去繼續執行。

繼續從AppRuntime的start函數看起:

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
     ...
    // 虛擬機器器建立及啟動,主要是關於虛擬機器器引數的設定
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);
    //註冊JNI方法
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android nativesn");
        return;
    }
    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
    //等價於strArray[0] = "com.android.internal.os.ZygoteInit"
    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);
      //strArray[1] = "start-system-server";
      //strArray[2] = "--abi-list=xxx";
      //其中xxx為系統響應的cpu架構型別,比如arm64-v8a.
    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);
    }
    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
     //將"com.android.internal.os.ZygoteInit"轉換為"com/android/internal/os/ZygoteInit
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'n", slashClassName);
        /* keep going */
    } else {
        //找到這個類後就繼續找成員函數main方法的Mehtod ID
        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 {
            // 通過Jni呼叫ZygoteInit.main()方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);
    ALOGD("Shutting down VMn");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main threadn");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanlyn");
}

start()函數主要做了三件事情,一呼叫startVm開啟虛擬機器器,二呼叫startReg註冊JNI方法,三就是使用JNI把Zygote程序啟動起來。

ZygoteInit

通過上述分析,程式碼進入了ZygoteInit.java中的main方法繼續執行。從這裡開始,就真正的啟動了Zygote程序。

我們從/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java這個檔案繼續往下看。

public static void main(String argv[]) {
        //ZygoteServer 是Zygote程序的Socket通訊伺服器端的管理類
        ZygoteServer zygoteServer = null;
        // 標記zygote啟動開始,呼叫ZygoteHooks的Jni方法,確保當前沒有其它執行緒在執行
        ZygoteHooks.startZygoteNoThreadCreation();
       //設定pid為0,Zygote進入自己的行程群組
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }
        Runnable caller;
        try {
            ...
            //開啟DDMS(Dalvik Debug Monitor Service)功能
            RuntimeInit.enableDdms();
            //解析app_main.cpp - start()傳入的引數
            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    //啟動zygote時,傳入了引數:start-system-server,會進入此分支
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    //啟動zygote_secondary時,才會傳入引數:enable-lazy-preload
                    enableLazyPreload = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    //SOCKET_NAME_ARG 為 zygote 或zygote_secondary,具體請參考 init.zyoget64_32.rc檔案
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }
            // 根據傳入socket name來決定是建立socket還是zygote_secondary
            final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }
            // In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first fork.
            // 在第一次zygote啟動時,enableLazyPreload為false,執行preload
            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                        SystemClock.uptimeMillis());
                // 載入程序的資源和類
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                Zygote.resetNicePriority();
            }
            // Do an initial gc to clean up after startup
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            gcAndFinalize();
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
            bootTimingsTraceLog.traceEnd(); // ZygoteInit
            // Disable tracing so that forked processes do not inherit stale tracing tags from
            // Zygote.
            Trace.setTracingEnabled(false, 0);
            Zygote.initNativeState(isPrimaryZygote);
            ZygoteHooks.stopZygoteNoThreadCreation();
            //  呼叫ZygoteServer 建構函式,建立socket Server端,會根據傳入的引數,
             // 建立兩個socket:/dev/socket/zygote 和 /dev/socket/zygote_secondary
            zygoteServer = new ZygoteServer(isPrimaryZygote);
            if (startSystemServer) {
                //fork出system server程序
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {
                    // 啟動SystemServer
                    r.run();
                    return;
                }
            }
            Log.i(TAG, "Accepting command socket connections");
           // ZygoteServer進入無限迴圈,處理請求
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {4
                zygoteServer.closeServerSocket();
            }
        }
        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }

main方法中主要做了以下幾件事:

  • 載入程序的資源和類。
  • 根據傳入socket name來建立socket server。
  • fork SystemServer 程序。

preload

既然preload方法是負責載入程序的資源和類,那麼它究竟載入了哪些資源和哪些類呢,這些資源又位於什麼位置呢?

我們先來看看preload方法裡具體做了什麼:

static void preload(TimingsTraceLog bootTimingsTraceLog) {
        beginPreload();
        //預載入類
        preloadClasses();
        cacheNonBootClasspathClassLoaders();
        //載入圖片、顏色等資原始檔
        preloadResources();
        //載入HAL相關內容
        nativePreloadAppProcessHALs();
       //載入圖形驅動
        maybePreloadGraphicsDriver();
        // 載入 android、compiler_rt、jnigraphics等library
        preloadSharedLibraries();
        //用於初始化文字資源
        preloadTextResources();
        //用於初始化webview;
        WebViewFactory.prepareWebViewInZygote();
        endPreload();
        warmUpJcaProviders();
        sPreloadComplete = true;
    }

preloadClasses

 private static void preloadClasses() {
        final VMRuntime runtime = VMRuntime.getRuntime();
        //preload classes 路徑為 /system/etc/preloaded-classes
        InputStream is;
        try {
            is = new FileInputStream(PRELOADED_CLASSES);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
            return;
        }
       ...
        try {
            BufferedReader br =
                    new BufferedReader(new InputStreamReader(is), Zygote.SOCKET_BUFFER_SIZE);
            int count = 0;
            String line;
            while ((line = br.readLine()) != null) {
                // Skip comments and blank lines.
                line = line.trim();
                if (line.startsWith("#") || line.equals("")) {
                    continue;
                }
                Trace.traceBegin(Trace.TRACE_TAG_DALVIK, line);
                try {
                   //使用Class.forName初始化類
                    Class.forName(line, true, null);
                    count++;
                } catch (ClassNotFoundException e) {
                    Log.w(TAG, "Class not found for preloading: " + line);
                } catch (UnsatisfiedLinkError e) {
                    Log.w(TAG, "Problem preloading " + line + ": " + e);
                } catch (Throwable t) {
                    Log.e(TAG, "Error preloading " + line + ".", t);
                    if (t instanceof Error) {
                        throw (Error) t;
                    }
                    if (t instanceof RuntimeException) {
                        throw (RuntimeException) t;
                    }
                    throw new RuntimeException(t);
                }
                Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
            }
        } catch (IOException e) {
            Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
        } finally {
           ...
        }
    }

可以看到,preloadClasses方法讀取/system/etc/preloaded-classes檔案的內容,並通過Class.forName初始化類。那麼在/system/etc/preloaded-classes檔案具體有哪些類呢?

由於內容過多,我這裡只擷取部分截圖讓大家看看具體裝載是什麼類。

從裝載列表中,我們可以看到很多熟悉的類,實際上,裝載的類都是我們應用程式執行時可能用到的java類。

preloadResources

private static void preloadResources() {
        final VMRuntime runtime = VMRuntime.getRuntime();
        try {
            mResources = Resources.getSystem();
            mResources.startPreloading();
            if (PRELOAD_RESOURCES) {
                Log.i(TAG, "Preloading resources...");
                long startTime = SystemClock.uptimeMillis();
                //裝載com.android.internal.R.array.preloaded_drawables中的圖片資源
                TypedArray ar = mResources.obtainTypedArray(
                        com.android.internal.R.array.preloaded_drawables);
                int N = preloadDrawables(ar);
                ar.recycle();
                Log.i(TAG, "...preloaded " + N + " resources in "
                        + (SystemClock.uptimeMillis() - startTime) + "ms.");
                startTime = SystemClock.uptimeMillis();
                //裝載com.android.internal.R.array.preloaded_color_state_lists中的顏色資源
                ar = mResources.obtainTypedArray(
                        com.android.internal.R.array.preloaded_color_state_lists);
                N = preloadColorStateLists(ar);
                ar.recycle();
                Log.i(TAG, "...preloaded " + N + " resources in "
                        + (SystemClock.uptimeMillis() - startTime) + "ms.");
                if (mResources.getBoolean(
                        com.android.internal.R.bool.config_freeformWindowManagement)) {
                    startTime = SystemClock.uptimeMillis();
                    //裝載com.android.internal.R.array.preloaded_freeform_multi_window_drawables中的圖片資源
                    ar = mResources.obtainTypedArray(
                            com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
                    N = preloadDrawables(ar);
                    ar.recycle();
                    Log.i(TAG, "...preloaded " + N + " resource in "
                            + (SystemClock.uptimeMillis() - startTime) + "ms.");
                }
            }
            mResources.finishPreloading();
        } catch (RuntimeException e) {
            Log.w(TAG, "Failure preloading resources", e);
        }
    }

從上述程式碼可以看到,preloadResources載入了特定的圖片資源和顏色資源。這些資源的路徑又具體在哪裡呢?

com.android.internal.R.array.preloaded_drawables的路徑位於/frameworks/base/core/res/res/values/arrays.xml中,其他的資源路徑也可以類似找到。各位讀者可以自行去該路徑下去看看所包含的資原始檔到底是什麼樣的。

preloadSharedLibraries

private static void preloadSharedLibraries() {
        Log.i(TAG, "Preloading shared libraries...");
        System.loadLibrary("android");
        System.loadLibrary("compiler_rt");
        System.loadLibrary("jnigraphics");
    }

preloadSharedLibraries裡的內容很簡單,主要是載入位於/system/lib目錄下的libandroid.so、libcompiler_rt.so、libjnigraphics.so三個so庫。

我們不妨想一下,為什麼android要在Zygote中將資源先進行預載入,這麼做有什麼好處?

這個問題留給各位讀者去自行思考,在這裡便不再回答了。

forkSystemServer

 private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
       ...
       //設定system server 
        String args[] = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
        ZygoteArguments parsedArgs = null;
        int pid;
        try {
            //將啟動引數封裝到ZygoteArguments類中
            parsedArgs = new ZygoteArguments(args);
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);
            boolean profileSystemServer = SystemProperties.getBoolean(
                    "dalvik.vm.profilesystemserver", false);
            if (profileSystemServer) {
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }
            //fork systemserver子程序,最終會進入com_android_internal_os_Zygote.cpp 類中fork程序並做一些初始化操作
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
        if (pid == 0) {
            //pid == 0 ,處理system server的邏輯
            if (hasSecondZygote(abiList)) {
                // 處理32_64和64_32的情況
                waitForSecondaryZygote(socketName);
            }
            // fork時會copy socket,system server需要主動關閉
            zygoteServer.closeServerSocket();
            // 裝載system server相關邏輯
            return handleSystemServerProcess(parsedArgs);
        }
        return null;
    }

forkSystemServer方法只是fork了一個Zygote的子程序,而handleSystemServerProcess方法構造了一個Runnable物件,建立一個子執行緒用於啟動SystemServer的邏輯。

private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
        Os.umask(S_IRWXG | S_IRWXO);
        if (parsedArgs.mNiceName != null) {
            //nicename 為 system_server
            Process.setArgV0(parsedArgs.mNiceName);
        }
        ...
        if (parsedArgs.mInvokeWith != null) {
            String[] args = parsedArgs.mRemainingArgs;
            // If we have a non-null system server class path, we'll have to duplicate the
            // existing arguments and append the classpath to it. ART will handle the classpath
            // correctly when we exec a new process.
            if (systemServerClasspath != null) {
                String[] amendedArgs = new String[args.length + 2];
                amendedArgs[0] = "-cp";
                amendedArgs[1] = systemServerClasspath;
                System.arraycopy(args, 0, amendedArgs, 2, args.length);
                args = amendedArgs;
            }
            WrapperInit.execApplication(parsedArgs.mInvokeWith,
                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);
            throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
        } else {
           //parsedArgs.mInvokeWith 為null,會進入此分支
            createSystemServerClassLoader();
            ClassLoader cl = sCachedSystemServerClassLoader;
            if (cl != null) {
                Thread.currentThread().setContextClassLoader(cl);
            }
            /*
             * Pass the remaining arguments to SystemServer.
             */
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mRemainingArgs, cl);
        }
        /* should never reach here */
    }

繼續從ZygoteInit.zygoteInit看起:

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
           ClassLoader classLoader) {
      ...
       RuntimeInit.commonInit();
       //註冊兩個jni函數
       //android_internal_os_ZygoteInit_nativePreloadAppProcessHALs
       //android_internal_os_ZygoteInit_nativePreloadGraphicsDriver
       ZygoteInit.nativeZygoteInit();
       return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
   }

RuntimeInit.applicationInit

protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
         //true代表應用程式退出時不呼叫AppRuntime.onExit(),否則會在退出前呼叫
        nativeSetExitWithoutCleanup(true);
       //設定虛擬機器器的記憶體利用率引數值為0.75
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        final Arguments args = new Arguments(argv);
        // Remaining arguments are passed to the start class's static main
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

繼續看findStaticMain:

 protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;
        try {
            //這裡className為 com.android.server.SystemServer
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }
        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }
        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }
        /*
         * This throw gets caught in ZygoteInit.main(), which responds
         * by invoking the exception's run() method. This arrangement
         * clears up all the stack frames that were required in setting
         * up the process.
         */
        return new MethodAndArgsCaller(m, argv);
    }

這裡通過反射獲得了 com.android.server.SystemServer 類中的main方法,並傳遞給MethodAndArgsCaller用於構造一個Runnable。只要執行此Runnable,就會開始呼叫com.android.server.SystemServer 類中的main方法。

到此,Zygote的邏輯已經全部執行完畢,android啟動進入了SystemServer的階段。

最後,我們再用一個流程圖來總結一下Zygote的業務邏輯:

以上就是Android10 啟動Zygote原始碼解析的詳細內容,更多關於Android10 啟動Zygote的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com