Android系统中应用程序进程的启动过程

Android系统中应用程序进程的启动过程,第1张

概述应用程序进程启动过程    当Android系统启动完成之后,我们安装的应用程序又是如何启动的呢?启动一个应用程序首先要保证该应用程序的进程已经被启动,本篇文章我们就基于Android8.1系统来分析应用程序进程启动过程。需要注意,是“应用程序进程启动过程”,不是“应用程序启动过 应用程序进程启动过程

       当AndroID系统启动完成之后,我们安装的应用程序又是如何启动的呢?启动一个应用程序首先要保证该应用程序的进程已经被启动,本篇文章我们就基于Android8.1系统来分析应用程序进程启动过程。需要注意,是“应用程序进程启动过程”,不是“应用程序启动过程”。

    1 应用程序进程简介

       要想启动一个应用程序,首先要保证这个应用程序所需要的应用程序进程已经启动。 AMS 在启动应用程序时会检查这个应用程序需要的应用程序进程是否存在,不存在就会请求Zygote 进程启动需要的应用程序进程。我们知道在 Zygote的Java 框架层中会创建 Server 端的 Socket ,这个 Socket 用来等待 AMS 请求 Zygote 来创建新的应用程序进程。Zygote 进程通过 fock 自身创建应用程序进程,这样应用程序进程就会获得 Zygote 进程在启动时创建的虚拟机实例。当然,在应用程序进程创建过程中除了获取虚拟机实例外,还创建了 Binder 线程池和消息循环,这样运行在应用进程中的应用程序就可以方便地使用 Binder 进行进程间通信以及处理消息了。(这里对Zygote进程不了解的可以先看"Android系统启动流程(2) —— 解析Zygote进程启动过程"这篇文章)。

     2 应用程序进程启动过程介绍

       应用程序进程创建过程的步骤分为两个部分,一部分是 AMS 发送启动应用程序进程请求,一部分是 Zygote 接收请求并创建应用程序进程。

     2.1 AMS发送启动应用程序进程的请求

       AMS如果想要启动应用程序首先就需要向Zygote进程发送创建应用程序进程的请求,AMS会通过调用startProcessLocked方法向Zygote进程发送请求,代码如下所示:

frameworks/base/services/core/java/com/androID/server/am/ActivityManagerService.java

    private final voID startProcessLocked(ProcessRecord app, String hostingType,            String hostingnameStr, String abiOverrIDe, String entryPoint, String[] entryPointArgs) {            ...         try {            try {                final int userID = UserHandle.getUserID(app.uID);                AppGlobals.getPackageManager().checkPackageStartable(app.info.packagename, userID);            } catch (remoteexception e) {                throw e.rethrowAsRuntimeException();            }            // 获取要创建的应用程序进程的用户ID            int uID = app.uID; // ... 1            int[] gIDs = null;            int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;            if (!app.isolated) {                int[] permGIDs = null;                ...                                /*                 * Add shared application and profile GIDs so applications can share some                 * resources like shared librarIEs and access user-wIDe resources                 */                // 对gID进程创建与赋值          ... 2                if (ArrayUtils.isEmpty(permGIDs)) {                    gIDs = new int[3];                } else {                    gIDs = new int[permGIDs.length + 3];                    System.arraycopy(permGIDs, 0, gIDs, 3, permGIDs.length);                }                gIDs[0] = UserHandle.getSharedAppGID(UserHandle.getAppID(uID));                gIDs[1] = UserHandle.getCacheAppGID(UserHandle.getAppID(uID));                gIDs[2] = UserHandle.getUserGID(UserHandle.getUserID(uID));            }                        ...            if (entryPoint == null) entryPoint = "androID.app.ActivityThread"; // ... 3            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +                    app.processname);            checkTime(startTime, "startProcess: asking zygote to start proc");            ProcessstartResult startResult;            if (hostingType.equals("webvIEw_service")) {                startResult = startWebVIEw(entryPoint,                        app.processname, uID, uID, gIDs, deBUGFlags, mountExternal,                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,                        app.info.dataDir, null, entryPointArgs);            } else {                // 启动应用程序进程                startResult = Process.start(entryPoint,                        app.processname, uID, uID, gIDs, deBUGFlags, mountExternal,                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,                        app.info.dataDir, invokeWith, entryPointArgs); // ... 4            }                        ...        } catch (RuntimeException e) {          ...        }    }
       在注释1处得到创建应用程序进程的用户ID ,在注释2处对用户组 ID (gIDs )进行创建和赋值。在注释3处如果 entryPoint 为null ,则赋值 androID.app.ActivityThread ,这个值就是应用程序进程主线程的类名。在注释4处调用 Process的start 方法,接下来查看 Process的start 方法,代码如下所示: 

frameworks/base/core/java/androID/os/Process.java

    public static final ProcessstartResult start(final String processClass,                                  final String nicename,                                  int uID, int gID, int[] gIDs,                                  int deBUGFlags, int mountExternal,                                  int targetSdkVersion,                                  String seInfo,                                  String abi,                                  String instructionSet,                                  String appDataDir,                                  String invokeWith,                                  String[] zygoteArgs) {        return zygoteProcess.start(processClass, nicename, uID, gID, gIDs,                    deBUGFlags, mountExternal, targetSdkVersion, seInfo,                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs); // ... 1    }

       在注释1处我们可以看到在Process的start方法中只调用了ZygoteProcess的start方法, 其中ZygoteProcess类用于保持与Zygote进程的通信状态。ZygoteProcess的start方法代码如下所示:

frameworks/base/core/java/androID/os/ZygoteProcess.java

    public final Process.ProcessstartResult start(final String processClass,                                                  final String nicename,                                                  int uID, int gID, int[] gIDs,                                                  int deBUGFlags, int mountExternal,                                                  int targetSdkVersion,                                                  String seInfo,                                                  String abi,                                                  String instructionSet,                                                  String appDataDir,                                                  String invokeWith,                                                  String[] zygoteArgs) {        try {            return startViaZygote(processClass, nicename, uID, gID, gIDs,                    deBUGFlags, mountExternal, targetSdkVersion, seInfo,                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs); // ... 1        } catch (ZygoteStartFailedEx ex) {            Log.e(LOG_TAG,                    "Starting VM process through Zygote Failed");            throw new RuntimeException(                    "Starting VM process through Zygote Failed", ex);        }    }

       在注释1处又调用了startViaZygote方法,代码如下所示:

frameworks/base/core/java/androID/os/ZygoteProcess.java

    private Process.ProcessstartResult startViaZygote(final String processClass,                                                      final String nicename,                                                      final int uID, final int gID,                                                      final int[] gIDs,                                                      int deBUGFlags, int mountExternal,                                                      int targetSdkVersion,                                                      String seInfo,                                                      String abi,                                                      String instructionSet,                                                      String appDataDir,                                                      String invokeWith,                                                      String[] extraArgs)                                                      throws ZygoteStartFailedEx {       /**        *  ... 1   创建字符串列表argsForZygote保存应用进程的启动参数        */        ArrayList<String> argsForZygote = new ArrayList<String>();        // --runtime-args, --setuID=, --setgID=,        // and --setgroups= must go first        argsForZygote.add("--runtime-args");        argsForZygote.add("--setuID=" + uID);        argsForZygote.add("--setgID=" + gID);        if ((deBUGFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {            argsForZygote.add("--enable-jni-logging");        }        if ((deBUGFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {            argsForZygote.add("--enable-safemode");        }        if ((deBUGFlags & Zygote.DEBUG_ENABLE_JDWP) != 0) {            argsForZygote.add("--enable-jDWp");        }        if ((deBUGFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {            argsForZygote.add("--enable-checkjni");        }        if ((deBUGFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {            argsForZygote.add("--generate-deBUG-info");        }        if ((deBUGFlags & Zygote.DEBUG_ALWAYS_JIT) != 0) {            argsForZygote.add("--always-jit");        }        if ((deBUGFlags & Zygote.DEBUG_NATIVE_DEBUGGABLE) != 0) {            argsForZygote.add("--native-deBUGgable");        }        if ((deBUGFlags & Zygote.DEBUG_JAVA_DEBUGGABLE) != 0) {            argsForZygote.add("--java-deBUGgable");        }        if ((deBUGFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {            argsForZygote.add("--enable-assert");        }        if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAulT) {            argsForZygote.add("--mount-external-default");        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {            argsForZygote.add("--mount-external-read");        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {            argsForZygote.add("--mount-external-write");        }        argsForZygote.add("--target-sdk-version=" + targetSdkVersion);        // --setgroups is a comma-separated List        if (gIDs != null && gIDs.length > 0) {            StringBuilder sb = new StringBuilder();            sb.append("--setgroups=");            int sz = gIDs.length;            for (int i = 0; i < sz; i++) {                if (i != 0) {                    sb.append(',');                }                sb.append(gIDs[i]);            }            argsForZygote.add(sb.toString());        }        if (nicename != null) {            argsForZygote.add("--nice-name=" + nicename);        }        if (seInfo != null) {            argsForZygote.add("--seinfo=" + seInfo);        }        if (instructionSet != null) {            argsForZygote.add("--instruction-set=" + instructionSet);        }        if (appDataDir != null) {            argsForZygote.add("--app-data-dir=" + appDataDir);        }        if (invokeWith != null) {            argsForZygote.add("--invoke-with");            argsForZygote.add(invokeWith);        }        argsForZygote.add(processClass);        if (extraArgs != null) {            for (String arg : extraArgs) {                argsForZygote.add(arg);            }        }        synchronized(mlock) {            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); // ... 2          }    }

       在注释1处创建了字符串列表argsForZygote,然后将应用程序进程的启动参数保存在列表中。最后再注释2处调用zygoteSendArgsAndGetResult方法,然而zygoteSendArgsAndGetResult方法需要传入的第一个参数是调用openZygoteSocketIfNeeded方法的返回值,第二个参数就是保存了应用程序的启动参数的argsForZygote列表,接下来我们先分析zygoteSendArgsAndGetResult方法,代码如下所示:

frameworks/base/core/java/androID/os/ZygoteProcess.java

    @GuardedBy("mlock")    private static Process.ProcessstartResult zygoteSendArgsAndGetResult(            ZygoteState zygoteState, ArrayList<String> args)            throws ZygoteStartFailedEx {        try {            // Throw early if any of the arguments are malformed. This means we can            // avoID writing a partial response to the zygote.            int sz = args.size();            for (int i = 0; i < sz; i++) {                if (args.get(i).indexOf('\n') >= 0) {                    throw new ZygoteStartFailedEx("embedded newlines not allowed");                }            }            /**             * See com.androID.internal.os.SystemZygoteInit.readArgumentList()             * Presently the wire format to the zygote process is:             * a) a count of arguments (argc, in essence)             * b) a number of newline-separated argument strings equal to count             *             * After the zygote process reads these it will write the pID of             * the child or -1 on failure, followed by boolean to             * indicate whether a wrapper process was used.             */            final BuffereDWriter writer = zygoteState.writer;            final DatainputStream inputStream = zygoteState.inputStream;            writer.write(Integer.toString(args.size()));            writer.newline();            for (int i = 0; i < sz; i++) {                String arg = args.get(i);                writer.write(arg);                writer.newline();            }            writer.flush();            // Should there be a timeout on this?            Process.ProcessstartResult result = new Process.ProcessstartResult();            // Always read the entire result from the input stream to avoID leaving            // bytes in the stream for future process starts to accIDentally stumble            // upon.            result.pID = inputStream.readInt();            result.usingWrapper = inputStream.readBoolean();            if (result.pID < 0) {                throw new ZygoteStartFailedEx("fork() Failed");            }            return result;        } catch (IOException ex) {            zygoteState.close();            throw new ZygoteStartFailedEx(ex);        }    }
       zygoteSendArgsAndGetResult 方法的主要作用就是将传入的应用进程的启动参数argsForZygote写入 ZygoteState 中, ZygoteState是ZygoteProcess 的静态内部类,用于表示与 Zygote 进程通信的状态。 ZygoteState 就是由openZygoteSocketIfNeeded方法返回,那么我们接着来看 openZygoteSocketIfNeeded 方法, 代码如下所示: 

frameworks/base/core/java/androID/os/ZygoteProcess.java

    @GuardedBy("mlock")    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {        Preconditions.checkState(Thread.holdsLock(mlock), "ZygoteProcess lock not held");        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {            try {                // 与Zygote进程建立Socket连接                primaryZygoteState = ZygoteState.connect(mSocket); // ... 1            } catch (IOException ioe) {                throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);            }        }        // 连接Zygote主模式返回的ZygoteState是否与启动应用程序进程所需要的ABI匹配        if (primaryZygoteState.matches(abi)) { // ... 2            return primaryZygoteState;        }        // The primary zygote dIDn't match. Try the secondary.        // 如果不匹配,则尝试连接Zygote辅模式        if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {            try {                secondaryZygoteState = ZygoteState.connect(mSecondarySocket); // ... 3            } catch (IOException ioe) {                throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);            }        }        // 连接Zygote辅模式返回的ZygoteState是否与启动应用程序进程所需要的ABI匹配        if (secondaryZygoteState.matches(abi)) { // ... 4            return secondaryZygoteState;        }        throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);    }
       在ZygoteInit的main方法中会创建 name 为"zygote"的 Server端Socket 。在注释1调用 ZygoteState的connect方法与名称为 “zygote”的Socket 建立连接,也就是说,在注释1处与 Zygote 进程建立 Socket 连接,并返回 ZygoteState 类型的 primaryZygoteState 对象,在注释2处如果 primaryZygoteState 与启动应用程序进程所 ABI 不匹配,则会在注释3处连接 name 为“zygote_secondary”的 Socket。Zygote 的启动脚本有4种,如果采用的是 init. zygote32_ 64.rc 或者 init. zygote64_32.rc, name 为“zygote ”的为主模式, name 为“zygote_secondary ”的为辅模式 ,那么注释2和注释3处的意思简单来说就是,如果连接 Zygote主模式返回的 ZygoteState 与启动应用程序进程所需的 ABI不匹配,则连接 Zygote 辅模式。如果在注释4处连接 Zygote辅模式返回的 ZygoteState 与启动应用程序进程所需的 ABI 也不匹配, 则抛出ZygoteStartFailedEx 异常。       2 Zygote 接收请求并创建应用程序进程       Socket 连接成功并匹配 ABI 后会返回 ZygoteState 类型对象,在分析zygoteSendArgsAndGetResult方法中讲过,会将应用进程的启动参数 argsForZygote 写入 ZygoteState 中,这样 Zygote 进程就会收到一个创建新的应用程序进程的请求,首先再分析一下Zygotelnit的main方法,代码如下所示: 

frameworks/base/core/java/com/androID/internal/os/Zygotelnit.java

public static voID main(String argv[]) {        ZygoteServer zygoteServer = new ZygoteServer()        ...         String socketname = "zygote";         ...                try {                         ...             // 创建一个Server端的Socket,socketname的值为"zygote"            zygoteServer.registerServerSocket(socketname); // ... 1            // 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());                 // 预加载类和资源                preload(boottimingsTraceLog); // ... 2                 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,                    SystemClock.uptimeMillis());                boottimingsTraceLog.traceEnd(); // ZygotePreload            } else {                Zygote.resetNicePriority();            }             ...             if (startSystemServer) {                // 启动SystemServer进程                Runnable r = forkSystemServer(abiList, socketname, 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.            // 等待AMS请求            caller = zygoteServer.runSelectLoop(abiList); // 4        } catch (Throwable ex) {            Log.e(TAG, "System zygote dIEd with exception", ex);            throw ex;        } finally {            zygoteServer.closeServerSocket();        }         // We're in the child process and have exited the select loop. Proceed to execute the        // command.        if (caller != null) {            caller.run();        }    }
       在注释1处通过 registerZygoteSocket 方法创建了一个Server 端的 Socket,这个name为“zygote”的 Socket 用来等待 AMS 请求 Zygote来创建新的应用程序进程。在注释2处预加载类和资源。在注释3启动 SystemServer 进程,这样系统的服务会由SystemServer进程启动起来。在注释4调用 ZygoteServer的runSelectLoop方法来等待 AMS 求创建新的应用程序进程。下面来查看 ZygoteServer的runSelectLoop方法,代码如下所示: 

frameworks/base/core/java/com/androID/internal/os/ZygoteServe.java

  Runnable runSelectLoop(String abiList) {               ...         // 无线循环等待AMS的请求        while (true) {                        ...            for (int i = pollFds.length - 1; i >= 0; --i) {                 if ((pollFds[i].revents & PolliN) == 0) {                    continue;                }                 if (i == 0) {                    ZygoteConnection newPeer = acceptCommandPeer(abiList);                    peers.add(newPeer);                    fds.add(newPeer.getfileDesciptor());                } else {                    try {                        ZygoteConnection connection = peers.get(i);                        final Runnable command = connection.processOneCommand(this); // ... 1                         if (mIsForkChild) {                            // We're in the child. We should always have a command to run at this                            // stage if processOneCommand hasn't called "exec".                            if (command == null) {                                throw new IllegalStateException("command == null");                            }                             return command;                        } else {                            // We're in the server - we should never have any commands to run.                            if (command != null) {                                throw new IllegalStateException("command != null");                            }                             // We don't kNow whether the remote sIDe of the socket was closed or                            // not until we attempt to read from it from processOneCommand. This shows up as                            // a regular PolliN event in our regular processing loop.                            if (connection.isClosedByPeer()) {                                connection.closeSocket();                                peers.remove(i);                                fds.remove(i);                            }                        }                    } catch (Exception e) {                       ...                                          }              }         }    }}
       当有 AMS 的请求数据到来时,会调用注释2处ZygoteConnection的processOneCommand方法来处理请求数据的,ZygoteConnection的processOneCommand方法的代码如下所示: frameworks/base/core/java/com/androID/internal/os/ZygoteConnection.java  
    Runnable processOneCommand(ZygoteServer zygoteServer) {        String args[];        Arguments parsedArgs = null;        fileDescriptor[] descriptors;        try {            // 获取应用进程的启动参数            args = readArgumentList(); // ... 1            descriptors = mSocket.getAncillaryfileDescriptors();        } catch (IOException ex) {            throw new IllegalStateException("IOException on command socket", ex);        }         ...        parsedArgs = new Arguments(args); // ... 2            ...        /**         *  ... 3   创建应用程序进程         */        pID = Zygote.forkAndSpecialize(parsedArgs.uID, parsedArgs.gID, parsedArgs.gIDs,                parsedArgs.deBUGFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,                parsedArgs.nicename, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,                parsedArgs.appDataDir);        try {            // 当前代码逻辑运行在子进程中            if (pID == 0) {                // in child                zygoteServer.setForkChild();                zygoteServer.closeServerSocket();                IoUtils.closeQuIEtly(serverPipeFd);                serverPipeFd = null;                // 处理应用程序进程                return handleChildProc(parsedArgs, descriptors, childPipeFd); // ... 4            } else {                // In the parent. A pID < 0 indicates a failure and will be handled in                // handleParentProc.                IoUtils.closeQuIEtly(childPipeFd);                childPipeFd = null;                handleParentProc(pID, descriptors, serverPipeFd);                return null;            }        } finally {            IoUtils.closeQuIEtly(childPipeFd);            IoUtils.closeQuIEtly(serverPipeFd);        }    }
       在注释1处调用 readArgumentList方法来获取应用程序进程的启动参数,并在注释2处将 readArgumentList方法返回的字符串数组 args 封装到 Arguments 类型的 parsedArgs 。在注释3处调用 Zygote的forkAndSpecialize方法来创建应用程序进程,参数为 parsedArgs 中存储的应用进程启动参数,返回值为 pID 。forkAndSpecialize方法主要是通 fork当前进程来创建一个子进程的,如果 pID 等于0, 则说明当前代码逻辑运行在新创建的子进程(应用程序 )中,这时就会调用 handleChildProc 方法来处理应用程序进程,代码如下所示: 

frameworks/base/core/java/com/androID/internal/os/ZygoteConnection.java

    private Runnable handleChildProc(Arguments parsedArgs, fileDescriptor[] descriptors,            fileDescriptor pipeFd) {        ...        if (parsedArgs.invokeWith != null) {            WrapperInit.execApplication(parsedArgs.invokeWith,                    parsedArgs.nicename, parsedArgs.targetSdkVersion,                    vmruntime.getCurrentInstructionSet(),                    pipeFd, parsedArgs.remainingArgs);            // Should not get here.            throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");        } else {            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,                    null /* classLoader */); // ... 1        }    }

       在注释1处调用ZygoteInit的zygoteInit方法,代码如下:

frameworks/base/core/java/com/androID/internal/os/Zygotelnit.java
    public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {        if (RuntimeInit.DEBUG) {            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");        }        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");        RuntimeInit.redirectLogStreams();        RuntimeInit.commonInit();        ZygoteInit.nativeZygoteInit(); // ... 1        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); // ... 2    }
       在注释1处会在新创建的应用程序进程中创建 Binder线程池, nativeZygotelnit是一个Native 方法,因此我们先要了解它对应的 JNI 文件,代码如下所示: 

frameworks/base/core/jni/AndroIDRuntime.cpp

int register_com_androID_internal_os_ZygoteInit_nativeZygoteInit(jnienv* env){    const JNINativeMethod methods[] = {        { "nativeZygoteInit", "()V",            (voID*) com_androID_internal_os_ZygoteInit_nativeZygoteInit },    };    return jniRegisterNativeMethods(env, "com/androID/internal/os/ZygoteInit",        methods, NELEM(methods));}

       通过JNI的gMethods 数组,可以看出 nativeZygotelnit 方法对应的是 JNI 文件 AndroIDRuntime.cpp的com_androID_internal_os _zygotelnit_ nativeZ ygotelnit 函数,代码如下所示:

frameworks/base/core/jni/AndroIDRuntime.cpp

static voID com_androID_internal_os_ZygoteInit_nativeZygoteInit(jnienv* env, jobject clazz){    gCurRuntime->onZygoteInit();}

       这里 gCurRuntime是AndroIDRuntime 类型的指针,具体指向的是 AndroIDRuntime的子类AppRuntime ,它在app_main.cpp 中定义,我们接着来查看 AppRuntime的onZygotelnit 方法,代码如下所示:

frameworks/base/cmds/app_process/app_main .cpp

    virtual voID onZygoteInit()    {        sp<Processstate> proc = Processstate::self();        ALOGV("App process: starting thread pool.\n");        proc->startThreadPool(); // ... 1    }

       注释1处的代码用来启动一个Binder线程池,接下来分析Processstate的startThreadPool方法,代码如下:

frameworks/native/libs/binder/Processstate.cpp
voID Processstate::startThreadPool(){    autoMutex _l(mlock);    if (!mThreadPoolStarted) { // ... 1        mThreadPoolStarted = true;        spawnPooledThread(true); // ... 2    }}
       支持Binder通信的进程中都有一个Processstate类 ,它里面有一个mThreadPoolStarted变量,用来表示Binder线程池是否已经被启动过,默认值为 false 。在每次调用 startThreadPool 函数时都会在注释1处先检查这个标记,从而确保 Binder 线程池只启动一次。如果 Binder线程池未被启动,则会在注释2处设置 mThreadPoolStarted为 true 并调用 spawnPooledThread 函数来创建线程池中的第一个线程,也就是线程池的主线程 ,代码如下所示: frameworks/native/libs/binder/Processstate.cpp
voID Processstate::spawnPooledThread(bool isMain){    if (mThreadPoolStarted) {        String8 name = makeBinderThreadname();        ALOGV("Spawning new pooled thread, name=%s\n", name.string());        sp<Thread> t = new PoolThread(isMain);        t->run(name.string()); //...1    }}

      可以看到Binder线程为一个PoolThread 。在注释1处调 PoolThread的run函数来启动一个新的线程。下面来查 PoolThread 类做了什么,代码如下:

frameworks/native/libs/binder/Processstate.cpp

class PoolThread : public Thread{public:    explicit PoolThread(bool isMain)        : mIsMain(isMain)    {    }    protected:    virtual bool threadLoop()    {        IPCThreadState::self()->joinThreadPool(mIsMain); // ... 1         return false;    }        const bool mIsMain;};
       PoolThread 类继承了Thread 类。在注释1处调用 IPCThreadState的joinThreadPool函数,将当前线程注册到 Binder 驱动程序中,这样我们创建的线程就加入了 Binder 线程池中, 新创建的应用程序进程就支持 Binder 进程间通信了,我们只需要创建当前进程的 Binder 对象,并将它注册到 ServiceManager 中就可以实现 Binder 进程间通信 ,而不必关心进程间是如何通过 Binder 进行通信的。       再回到Zygotelnit的zygoteInit方法的注释2处调用了 Runtimelnit的applicationlnit方法,代码如下: frameworks/base/core/java/com/androID/internal/os/Runtimelnit.java
    protected static Runnable applicationInit(int targetSdkVersion, String[] argv,            ClassLoader classLoader) {        // If the application calls System.exit(), terminate the process        // immediately without running any shutdown hooks.  It is not possible to        // shutdown an AndroID application gracefully.  Among other things, the        // AndroID runtime shutdown hooks close the Binder driver, which can cause        // leftover running threads to crash before the process actually exits.        nativeSetExitWithoutCleanup(true);        // We want to be fairly aggressive about heap utilization, to avoID        // holding on to a lot of memory that isn't needed.        vmruntime.getRuntime().setTargetHeaputilization(0.75f);        vmruntime.getRuntime().setTargetSdkVersion(targetSdkVersion);        final Arguments args = new Arguments(argv);        // The end of of the RuntimeInit event (see #zygoteInit).        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);        // Remaining arguments are passed to the start class's static main        return findStaticMain(args.startClass, args.startArgs, classLoader); // ... 1    }

       在注释1处调用findStaticMain方法,第一个参数agrs.startClass,它指的就是本文开头提到的参数"androID.app.ActivityThread"。接下来分析findStaticMain方法,代码如下所示:

frameworks/base/core/java/com/androID/internal/os/Runtimelnit.java

    private static Runnable findStaticMain(String classname, String[] argv,            ClassLoader classLoader) {        Class<?> cl;        try {            // 获得androID.app.ActivityThread类            cl = Class.forname(classname, true, classLoader); // ... 1        } catch (ClassNotFoundException ex) {            throw new RuntimeException(                    "Missing class when invoking static main " + classname,                    ex);        }        Method m;        try {            // 获得ActivityThread的main方法            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); // ... 3    }

      可以看到在注释1通过反射获得了androID.app.ActivityThread 类,接下来在注释2处获得了 ActivityThread的main 法,在注释3处将找到的 main 方法传入 MethodAndArgsCaller 类中,MethodAndArgsCaller 实现了Runnable接口,代码如下:

frameworks/base/core/java/com/androID/internal/os/Runtimelnit.java

    static class MethodAndArgsCaller implements Runnable {        /** method to call */        private final Method mMethod;         /** argument array */        private final String[] mArgs;         public MethodAndArgsCaller(Method method, String[] args) {            mMethod = method;            mArgs = args;        }         public voID run() {            try {                // 通过invoke调用ActivityThread的main方法                mMethod.invoke(null, new Object[] { mArgs }); // ... 1            } catch (illegalaccessexception ex) {                throw new RuntimeException(ex);            } catch (InvocationTargetException ex) {                Throwable cause = ex.getCause();                if (cause instanceof RuntimeException) {                    throw (RuntimeException) cause;                } else if (cause instanceof Error) {                    throw (Error) cause;                }                throw new RuntimeException(ex);            }        }    }}

       在注释1处通过invoke调用ActivityThread的main方法,那么MethodAndArgsCaller 的run方法又是在哪里调用的呢?findStaticMain方法最终会将MethodAndArgsCaller方法返回给ZygoteInit的main方法中的callercan参数,代码如下所示:

frameworks/base/core/java/com/androID/internal/os/Zygotelnit.java

    public static voID main(String argv[]) {               final Runnable caller;        try {                       ...            caller = zygoteServer.runSelectLoop(abiList);        } catch (Throwable ex) {            Log.e(TAG, "System zygote dIEd with exception", ex);            throw ex;        } finally {            zygoteServer.closeServerSocket();        }        // We're in the child process and have exited the select loop. Proceed to execute the        // command.        if (caller != null) {            caller.run(); // ... 1        }    }

        在注释1处,调用caller.run方法就会调用到MethodAndArgsCaller的run方法,然后通过invoke就进入到ActivityThread的main方法,这样应用程序进程就启动了。

    3. 消息循环创建过程       应用程序进程启动后会创建消息循环,MethodAndArgsCaller的run方法执行是会通过invoke调用ActivityThread的main方法,代码如下所示: frameworks/base/core/java/androID/app/ActivityThread.java
    public static voID main(String[] args) {        ...            // 创建主线程的Looper        Looper.prepareMainLooper(); // ... 1        ActivityThread thread = new ActivityThread(); // ... 2        thread.attach(false);        if (sMainThreadHandler == null) { // ... 3            // 创建主线程的H类            sMainThreadHandler = thread.getHandler(); // ... 4        }        if (false) {            Looper.myLooper().setMessageLogging(new                    LogPrinter(Log.DEBUG, "ActivityThread"));        }        // End of event ActivityThreadMain.        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);        // Looper开始工作        Looper.loop(); // ... 5        throw new RuntimeException("Main thread loop unexpectedly exited");    }
       ActivityThread 类用于管理当前应用程序进程的主线程,在注释1处创建主线程的消息循环 Looper ,在注释2处创建 ActivityThread 。在注释3判断 Handler 类型的 sMainThreadHandler 否为 null ,如果为 null 则在注释4处获取H类并赋值给 sMainThreadHandler ,这个类继承自 Handler ,是 ActivityThread 的内部类,用于处理主线程的消息循环,在注释5调用 Looper 的loop方法,使得 Looper 开始处理消息。可以看出,系统在应用程序进程启动完成后,就会创建一个消息循环,这样运行在应用程序进程中的应用程序可以方便地使用消息处理机制。 总结

以上是内存溢出为你收集整理的Android系统中应用程序进程的启动过程全部内容,希望文章能够帮你解决Android系统中应用程序进程的启动过程所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1058805.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-25
下一篇2022-05-25

发表评论

登录后才能评论

评论列表(0条)

    保存