zygote进程

0

源码解析基于Android 11

前言

What:zygote的作用是什么?

  • How:zygote的启动流程是什么?

    - 启动的时候做了什么事,有哪些关键步骤?

  • Why:zygote的工作原理是什么?

    - 怎么启动进程,如何跟别人通信?

  • 这道题想考察什么?

    - 了解Zygote的作用(初级)

    - 熟悉Zygote的启动流程(中级)

    - 深刻理解Zygote的工作原理(高级)

  • 可参考文章

    - https://github.com/jeanboydev/Android-ReadTheFuckingSourceCode/tree/master/article/android

    - https://superandroid.pro/2020/03/06/android-10-xi-tong-qi-dong-xi-lie-zygote-jin-cheng-fu-hua-qi/

1、 Zygote的作用

    Zygote 的字面意思就是受精卵,我们身上的所有细胞基本都是源于受精卵有丝分裂而来,而zygote进程对于Android系统的意义也如同受精卵对于生命的意义一般。Android系统中所有的应用进程以及系统进程都是由zygote创建出来的。

        zygote进程主要负责创建 Java 虚拟机,加载系统资源,启动 SystemServer 进程,以及在后续运行过程中启动普通的应用程序。

        1、启动SystemServer

            为什么SystemServer要在zygote里面启动:

            需要使用zygote准备好的相关系统资源:常用类, JNI函数, 主题资源, 共享库

        2、孵化应用进程

2、zygote的启动流程

    

2.1、进程是怎么启动的?

前文讲到, zygote 进程是init 进程解析rc文件之后创建的,所对应的可执行文件是/system/bin/app_process。进入App_main.cpp的main()函数。故zygote是通过fork和execv共同创建的。

在 init.rc 文件头部有这么一句: import /init.${ro.zygote}.rc

从android5.0开始,android开始支持64位的编译,zygote本身也就有了32位和64位的区别,所以在这里用ro.zygote属性来控制启动不同版本的zygote进程。

其中 ${ro.zygote} 会被替换成 ro.zyogte 的属性值,这主要是因为 Android 5.0 以后开始支持 64 位程序,为了兼容 32 位和 64 位才这样定义。 有四个值:zygote32、zygote64、zygote32_64、zygote64_32 ,也就是说可能有四种 .rc 文件,分别是:

init.zygote32.rc:zygote 进程对应的执行程序是 app_process(纯 32bit 模式)。

    - init.zygote64.rc:zygote 进程对应的执行程序是 app_process64(纯 64bit 模式)。

    - init.zygote32_64.rc:启动两个 zygote 进程(名为 zygote 和 zygote_secondary),对应的执行程序分别是 app_process32(主模式)、app_process64。

    - init.zygote64_32.rc:启动两个 zygote 进程(名为 zygote 和 zygote_secondary),对应的执行程序分别是 app_process64(主模式)、app_process32。

        在 init.zygote64_32.rc 文件中的头部我们可以看到 zygote 对应的二进制文件是 /system/bin/app_process64 (以此为例),

        其实不管是 app_process、app_process32 还是 app_process64,对应的源文件都是 app_main.cpp。

        最终 在\android\frameworks\base\cmds\app_process\app_main.cpp 的 main方法启动init.rc中定义的服务,如 zygote servicemanager 和 zygote 等服务。

    

2.2、 zygote进程启动之后做了什么?

zygote进程启动后的逻辑主要分为两部分:1是native层的逻辑 2是Java层的逻辑。

2.2.1 Zygote的Native层逻辑

    Zygote的native 层逻辑主要是为了进入Java层逻辑做准备。

    Zygote是由init进程通过解析init.zygote.rc文件而创建的,zygote所对应的可执行程序app_process,所对应的源文件是App_main.cpp,进程名为zygote。

    在App_main.cpp mian方法中主要是 设置进程名,解析AndroidRuntime 启动参数。

    然后通过AndroidRuntime的start方法做主要的工作

    1、启动Android虚拟机

        AndroidRuntime->Start() - >startVm()

    2、注册Android的JNI函数

        AndroidRuntime->Start() - >startReg()

    3、进入Java层

        在AndroidRuntime->Start() -方法的最后会反射调用ZygoteInit.java 的main方法从而进入zygote的Java世界

frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[])
{

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]

    ··········(中间省略逻辑为解析runtime参数)

    // Parse runtime arguments.  Stop at first unrecognized option.
    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模式
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } 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.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {
        ·······(启动Application)
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        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) {
        //如果当前是zygote mode 则加载ygote
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        //如果当前是application mode 则加载zygote
        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.");
    }
}

可以看到app_main.cpp 主要的工作就是解析参数,然后通过runtime去做真正的启动工作 (通过筛选AppRuntime 可以查看相关log)

frameworks/base/core/jni/AndroidRuntime.cpp


/*
 * Start the Android runtime.  This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method in the class
 * named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{

   ······

    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);

    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;

    //启动虚拟机
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * 注册JNI方法
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        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;

    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);

    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.
     */

     //找到zygote class类
    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 {
        //找到zygote main 函数的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 {
            // 通过反射调用ZygoteInit 的 main 方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);

    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

2.2.2 Zygote的Java层逻辑

Zygote进入Java层的入口就是main函数,main函数主要干了三件事

① 预加载资源

② 启动SystemServer

③ 进行loop循环

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

   /**
     * This is the entry point for a Zygote process.  It creates the Zygote server, loads resources,
     * and handles other tasks related to preparing the process for forking into applications.
     *
     * This process is started with a nice value of -20 (highest priority).  All paths that flow
     * into new processes are required to either set the priority to the default value or terminate
     * before executing any non-system code.  The native side of this occurs in SpecializeCommon,
     * while the Java Language priority is changed in ZygoteInit.handleSystemServerProcess,
     * ZygoteConnection.handleChildProc, and Zygote.usapMain.
     *
     * @param argv  Command line arguments used to specify the Zygote's configuration.
     */
    @UnsupportedAppUsage
    public static void main(String argv[]) {
        ZygoteServer zygoteServer = null;

        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        ZygoteHooks.startZygoteNoThreadCreation();

        // Zygote goes into its own process group.
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }

        Runnable caller;
        try {
            // Store now for StatsLogging later.
            final long startTime = SystemClock.elapsedRealtime();
            final boolean isRuntimeRestarted = "1".equals(
                    SystemProperties.get("sys.boot_completed"));

            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
            TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
                    Trace.TRACE_TAG_DALVIK);
            bootTimingsTraceLog.traceBegin("ZygoteInit");
            RuntimeInit.preForkInit();

            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;

             //解析app_main.cpp - start()传入的参数
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    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)) {
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
            if (!isRuntimeRestarted) {
                if (isPrimaryZygote) {
                    FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                            BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__ZYGOTE_INIT_START,
                            startTime);
                } else if (zygoteSocketName.equals(Zygote.SECONDARY_SOCKET_NAME)) {
                    FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                            BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SECONDARY_ZYGOTE_INIT_START,
                            startTime);
                }
            }

            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.
            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                        SystemClock.uptimeMillis());

                //1、 预加载相关资源       
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            }

            // Do an initial gc to clean up after startup
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            gcAndFinalize();
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

            bootTimingsTraceLog.traceEnd(); // ZygoteInit

            Zygote.initNativeState(isPrimaryZygote);

            ZygoteHooks.stopZygoteNoThreadCreation();

            zygoteServer = new ZygoteServer(isPrimaryZygote);

            //2、 启动systemServer
            if (startSystemServer) {
                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) {
                    r.run();
                    return;
                }
            }

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

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            // 3、进入loop循环,处理请求
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }

① 预加载资源

预加载资源主要,预加载 类、图片颜色等资源文件,而且只在zygote进程启动的时候只加载一次。zygote fork子进程时,子进程可以直接使用该资源不需要重新加载。

预加载的原理: zygote进程启动后将资源读取出来,保存到Resources一个全局静态变量中,下次读取系统资源的时候优先从静态变量中查找。

  static void preload(TimingsTraceLog bootTimingsTraceLog) {
        Log.d(TAG, "begin preload");

       ······
        beginPreload();
       ······

        //预加载类
        preloadClasses();

        //加载图片、颜色等资源文件
        preloadResources();

        nativePreloadAppProcessHALs();

        maybePreloadGraphicsDriver();

       // 预加载类库
        preloadSharedLibraries(); 

         //预加载文字资源
        preloadTextResources();
        // Ask the WebViewFactory to do any initialization that must run in the zygote process,
        // for memory sharing purposes. 初始化webView
        WebViewFactory.prepareWebViewInZygote();
        endPreload();
        warmUpJcaProviders();
        Log.d(TAG, "end preload");

        sPreloadComplete = true;
    }

② 启动系统服务

    /**
     * Prepare the arguments and forks for the system server process.
     *
     * @return A {@code Runnable} that provides an entrypoint into system_server code in the child
     * process; {@code null} in the parent.
     */
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        long capabilities = posixCapabilitiesAsBits(
                OsConstants.CAP_IPC_LOCK,
                OsConstants.CAP_KILL,
                OsConstants.CAP_NET_ADMIN,
                OsConstants.CAP_NET_BIND_SERVICE,
                OsConstants.CAP_NET_BROADCAST,
                OsConstants.CAP_NET_RAW,
                OsConstants.CAP_SYS_MODULE,
                OsConstants.CAP_SYS_NICE,
                OsConstants.CAP_SYS_PTRACE,
                OsConstants.CAP_SYS_TIME,
                OsConstants.CAP_SYS_TTY_CONFIG,
                OsConstants.CAP_WAKE_ALARM,
                OsConstants.CAP_BLOCK_SUSPEND
        );
        /* Containers run without some capabilities, so drop any caps that are not available. */
        StructCapUserHeader header = new StructCapUserHeader(
                OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
        StructCapUserData[] data;
        try {
            data = Os.capget(header);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to capget()", ex);
        }
        capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);

        /* Hardcoded command line to start the 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,3011",
                "--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 {
            parsedArgs = new ZygoteArguments(args);
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);

            if (Zygote.nativeSupportsTaggedPointers()) {
                /* Enable pointer tagging in the system server. Hardware support for this is present
                 * in all ARMv8 CPUs. */
                parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
            }

            /* Enable gwp-asan on the system server with a small probability. This is the same
             * policy as applied to native processes and system apps. */
            parsedArgs.mRuntimeFlags |= Zygote.GWP_ASAN_LEVEL_LOTTERY;

            if (shouldProfileSystemServer()) {
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }

            /* Request to fork the system server process */
            //通过fork方式生成 systemServer子进程
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }

forkSystemServer()会在新fork出的子进程中调用 handleSystemServerProcess(),

主要是返回Runtime.java的MethodAndArgsCaller的方法,然后通过r.run() 启动com.android.server.SystemServer的main 方法

③ runSelectLoop()

/

frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

  • 要注意的细节

    - Zygote fork要单线程(多线程fork 容易死锁或者线程状态不一致)

    - Zygote的IPC没有采用binder(使用本地socket)

  • 两个问题

    - 1、孵化应用进程这种事为什么不交给SystemServer来做,而专门设计一个Zygote?

        - 我们知道,应用在启动的时候需要做很多准备工作,包括启动虚拟机,加载各类系统资源等等,这些都是非常耗时的,如果能在zygote里就给这些必要的初始化工作做好,子进程在fork的时候就能直接共享,那么这样的话效率就会非常高。这个就是zygote存在的价值,这一点呢SystemServer是替代不了的,主要是因为SystemServer里跑了一堆系统服务,这些是不能继承到应用进程的。而且我们应用进程在启动的时候,内存空间除了必要的资源外,最好是干干净净的,不要继承一堆乱七八糟的东西。所以呢,不如给SystemServer和应用进程里都要用到的资源抽出来单独放在一个进程里,也就是这的zygote进程,然后zygote进程再分别孵化出SystemServer进程和应用进程。孵化出来之后,SystemServer进程和应用进程就可以各干各的事了。

    - 2、Zygote的IPC通信机制为什么不采用binder?如果采用binder的话会有什么问题么?

        - 第一个原因,我们可以设想一下采用binder调用的话该怎么做,首先zygote要启用binder机制,需要打开binder驱动,获得一个描述符,再通过mmap进行内存映射,还要注册binder线程,这还不够,还要创建一个binder对象注册到serviceManager,另外AMS要向zygote发起创建应用进程请求的话,要先从serviceManager查询zygote的binder对象,然后再发起binder调用,这来来回回好几趟非常繁琐,相比之下,zygote和SystemServer进程本来就是父子关系,对于简单的消息通信,用管道或者socket非常方便省事。第二个原因,如果zygote启用binder机制,再fork出SystemServer,那么SystemServer就会继承了zygote的描述符以及映射的内存,这两个进程在binder驱动层就会共用一套数据结构,这显然是不行的,所以还得先给原来的旧的描述符关掉,再重新启用一遍binder机制,这个就是自找麻烦了。

zygote的工作机制

  • loop如何处理请求

    - zZygoteInit.java ->runSelectLoop() ->ZygoteConnection.java->runOnce()

  • 3 进行loop循环 ZygoteInit.java ->runSelectLoop()

    -

  • 2 启动SystemServer ZygoteInit.java -> startSystemServer()

  • preloadClasses();

    - 通过反射方式预加载位于/system/etc/preloaded-classes文件中的类

    - 可以通过 adb shell cat /system/etc/preloaded-classes 命令查看 里面都是一些Java 和 Android 常用的类

  • preloadResources();

    - 预加载资源,包含drawable和color资源

  • preloadOpenGL()

    - 预加载OpenGL

  • preloadSharedLibraries();

    - //通过System.loadLibrary()方法, 预加载"android","compiler_rt","jnigraphics"这3个共享库

  • preloadTextResources()

    - 预加载 文本连接符资源 ;

  • WebViewFactory.prepareWebViewInZygote();

    - 仅用于zygote进程,用于内存共享的进程

  • zygote进程内加载了preload()方法中的所有资源,当需要fork新进程时,采用copy on write技术,这也是为什么启动应用进程要交由zygote来做的原因。

  • 1 预加载资源 ZygoteInit.java -> preload()

    - 在preload 主要是加载 类、drawable color openGl

流程图

Zygote的Java世界 ZygoteInit.java -> main()

由父进程fork出来的子进程如果终止了,那么父进程会受到SIGCHILD信号

5.1 为什么SystemServer和Zygote之间通信要采用Socket
进程间通信我们常用的是binder,为什么这里要采用socket呢。
主要是为了解决fork的问题:

UNIX上C++程序设计守则3:多线程程序里不准使用fork
Binder通讯是需要多线程操作的,代理对象对Binder的调用是在Binder线程,需要再通过Handler调用主线程来操作。
比如AMS与应用进程通讯,AMS的本地代理IApplicationThread通过调用ScheduleLaunchActivity,调用到的应用进程ApplicationThread的ScheduleLaunchActivity是在Binder线程,
需要再把参数封装为一个ActivityClientRecord,sendMessage发送给H类(主线程Handler,ActivityThread内部类)
主要原因:害怕父进程binder线程有锁,然后子进程的主线程一直在等其子线程(从父进程拷贝过来的子进程)的资源,但是其实父进程的子进程并没有被拷贝过来,造成死锁。

所以fork不允许存在多线程。而非常巧的是Binder通讯偏偏就是多线程,所以干脆父进程(Zgote)这个时候就不使用binder线程

5.2为什么一个java应用一个虚拟机?
android的VM(vm==Virtual Machine )也是类似JRE的东西,当然,各方面都截然不同,不过有一个作用都是一样的,为app提供了运行环境
android为每个程序提供一个vm,可以使每个app都运行在独立的运行环境,使稳定性提高。
vm的设计可以有更好的兼容性。android apk都被编译成字节码(bytecode),在运行的时候,vm是先将字节码编译真正可执行的代码,否则不同硬件设备的兼容是很大的麻烦。
android(非ROOT)没有windows下键盘钩子之类的东西,每个程序一个虚拟机,各个程序之间也不可以随意访问内存,所以此类木马病毒几乎没有。

5.3 什么是Zygote资源预加载
预加载是指在zygote进程启动的时候就加载,这样系统只在zygote执行一次加载操作,所有APP用到该资源不需要再重新加载,减少资源加载时间,加快了应用启动速度,一般情况下,系统中App共享的资源会被列为预加载资源。
zygote fork子进程时,根据fork的copy-on-write机制可知,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用。

5.4 Zygote为什么要预加载

应用程序都从Zygote孵化出来,应用程序都会继承Zygote的所有内容。

    如果在Zygote启动的时候加载这些类和资源,这些孵化的应用程序就继承Zygote的类和资源,这样启动引用程序的时候就不需要加载类和资源了,启动的速度就会快很多。

    开机的次数不多,但是启动应用程序的次数非常多。

5.5 Zygote 预加载的原理是什么?
zygote进程启动后将资源读取出来,保存到Resources一个全局静态变量中,下次读取系统资源的时候优先从静态变量中查找。

总结