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

应用程序进程启动过程

       当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 为 nu ll ,则赋值 android.app.Activ ityThread ,这个 值就是应用程序进程主线程的类名。在注释4处调用 Process的s tart 方法 接下来查看 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 方法的主要作用就是将传入的应用进程的启 动参数 argsF orZ ygo te写入  ZygoteState 中, ZygoteState是ZygoteProcess 的静态内部类,用于表示与 Zygote 进程通信的状态。   ZygoteS tate 就是 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" 的 S erver端 Socket 。在注释1调 Zy got eState的 co nn ect方法 与名称为
“zygote”的 Socket 建 立连接, 也就是说,在注释1处与 Zygote 进程建立 Socket 连接,并返回 ZygoteState 类型的 primaryZ ygoteState 对象,在注释2 处如果 primaryZygoteState 与启动应用程序进程所 ABI 不匹配,则 会在注释3 处连接  name 为“ zygote_ secondary ”的 Socket Zygote 的启动脚 本有4 种,如果采用的是 i nit. zy go te32 _ 64.rc 或者 init. zy gote64_32.rc name 为“ zygote ”的为 主模 式, name 为“ zygote_ secondary ”的为辅 模式 ,那么注释2 和注释3处的意思简单来说就是,如 果连接 Zygote主 模式 返回的 ZygoteState 与启动应用程 序进程所需的 ABI 不匹配,则 连接 Zygote 辅模式。如果在注释4处 连接 Zygo te辅 模式返回的 Zy goteS tate  与启动应用程序进程所需的 ABI 也不匹配, 则抛出 ZygoteStartFailed Ex 异常。
 

     2 Zygote 接收请求并创建应用程序进程

       Socket 连接成功并匹配 ABI 后会返回 ZygoteState 类型对象,在分析zyg oteSendArg sAndGe tR es ult方法 中讲过,会将应用进程的启动参数 argsF orZ ygote 写入 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 请求 Zygo te来 建新的应用 程序进程。 在注释2 处预加 载类和 资源。在注释3 启动 S yste mS erv er 进程,这样系统 的服务 会由SystemServer 进程启动起来。在注释4 调用 Z yg ot eServer的 runSelectLoop方法 来等待 AMS 求创 建新的应用程序进程。下面来查看 Z yg ot eServer的 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 ZygoteCo nnection的processOneCommand方法 来处理请求数据的, ZygoteCo nnection的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 处调用 r eadArgum entLi st方法 来获取应用程序进程的启动参数,并在注释2 处将 readArgumentList方法 返回的字符串数组 args 封装到 Arguments 类型的 parsedArgs 。在注释3 处调用 Zygote的 forkAndS peciali ze方法 来创建应用程序进程,参数为 parsedArgs 中存储的应用进程启动参数,返回值为 pid 。 forkAndS pecia lize方法 主要是通 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 通信的进程中都 有一个 Process State类  ,它里面 有一个 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;
};
       Pool Thread 类继 承了 Thread 类。在注释1 处调用 IPCThr ea dState的 joinThreadPool函数 ,将当前线程注册到 Binder 驱动程序中,这样我们创建的线程就加入了 Binder 线程池中, 新创建的应用程序进程就支持 Binder 进程间通信了,我们只 需要 创建当前 进程的 Binder 对象,并将它注册到 Service Manager 中就可以实现 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 类并赋值给
sMain ThreadHandler ,这个 类继承自 Handler ,是 ActivityThread 的内部类,用于处理主线程的消息循环, 在注释5调 Looper 的 loop方法 ,使得 Looper 开始处理消息。可以看出,系统在应用程序进程启动完成后,就会创建一个消息循环,这样运行在应用程序进程中的应用程序可以方便地使用消息处理机制。

猜你喜欢

转载自blog.csdn.net/lixiong0713/article/details/106801241