深入理解Android之应用程序进程启动流程

在上一篇文章深入理解Android 之 Activity启动流程中,应用程序根Activity的启动过程通过系统源码梳理了一遍,其中还有一个细节便是Android每个应用都是都是一个应用进程,而应用进程不会凭空产生,本文则通过系统源码继续探究Android应用程序进程启动流程(文中源码基于Android 10 )。

  • Android源码地址

  • 首先照例还是先看一个脑图,在自己大脑中能产生初步印象

应用程序进程启动过程.png

ActivityManagerService请求Zygote启动应用程序进程

AMS处理启动应用程序基本数据

  • 上一篇文章第二小节分析中提到了ActivityStackSupervisor的startSpecificActivityLocked的方法

frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // Activity应用程序进程是否已经准备好
        final WindowProcessController wpc =
                mService.getProcessController(r.processName, r.info.applicationInfo.uid);

        boolean knownToBeDead = false;
        if (wpc != null && wpc.hasThread()) { //1
            try {
                realStartActivityLocked(r, wpc, andResume, checkConfig); //2
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }
        .......
        }

        .......
        try {
           .......
            // Post message to start process to avoid possible deadlock of calling into AMS with the
            // ATMS lock held.  Hnadler发消息 避免死锁
            final Message msg = PooledLambda.obtainMessage(
                    ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
                    r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());//3
            mService.mH.sendMessage(msg);
        }
        ........
    }
  • 由以前源码注释1和2如果应用程序进程已经存在,则继续启动Activity逻辑,否则来到注释3出,我们看到关键部分ActivityManagerInternal::startProcess,"::"是Java 8 新增特性,相当于调用了ActivityManagerInternal的startProcess方法,而ActivityManagerInternal(frameworks/base/core/java/android/app/ActivityManagerInternal.java)是一个抽象类,它是Activity管理器本地服务接口,它的实现为AMS的内部类LocalService,它注册在AMS启动的过程,通过LocalServices(frameworks/base/core/java/com/android/server/LocalServices.java)注册,此类的使用方式与ServiceManager相似,不同之处在于,此处注册的服务不是Binder对象,并且只能在同一进程(SystemServer进程)中使用。也就是说ActivityManagerInternal实现类LocalService是SystemServer进程的本地服务Service,通过本地服务注册到LocalServices中,而AMS也是运行在SystemServer进程,则可以直接使用LocalService。所以注释3处调用了LocalService的startProcess方法

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

 @Override
        public void startProcess(String processName, ApplicationInfo info,
                boolean knownToBeDead, String hostingType, ComponentName hostingName) {
            try {
                if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
                            + processName);
                }
                synchronized (ActivityManagerService.this) {
                    startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                            new HostingRecord(hostingType, hostingName),
                            false /* allowWhileBooting */, false /* isolated */,
                            true /* keepIfLarge */);//
                }
            } 
            .......
        }
        
final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            HostingRecord hostingRecord, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
                hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */); //2 
    }        

  • 由以上源码注释1处调用了startProcessLocked方法,由注释2处则调用了 ProcessList的 startProcessLocked方法,ProcessList是处理Activity进程的管理类,接着往下看

frameworks/base/services/core/java/com/android/server/am/ProcessList.java

@GuardedBy("mService")
    final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
            boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
        long startTime = SystemClock.elapsedRealtime();
        ProcessRecord app;
        ..........

        if (app == null) {
            checkSlow(startTime, "startProcess: creating new process record");
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord);//1
            if (app == null) {
                Slog.w(TAG, "Failed making new process record for "
                        + processName + "/" + info.uid + " isolated=" + isolated);
                return null;
            }
            app.crashHandler = crashHandler;
            app.isolatedEntryPoint = entryPoint;
            app.isolatedEntryPointArgs = entryPointArgs;
            checkSlow(startTime, "startProcess: done creating new process record");
        }

        .....
        
        final boolean success = startProcessLocked(app, hostingRecord, abiOverride);//2
        checkSlow(startTime, "startProcess: done starting proc!");
        return success ? app : null;
    }
  • 由以上代码,注释1处创建了ProcessRecord对象,它保存了当前正在运行的特定进程的完整信息,也就是需要启动的应用程序进程,接着注释2继续调用startProcessLocked方法

frameworks/base/services/core/java/com/android/server/am/ProcessList.java

 /**
     * @return {@code true} if process start is successful, false otherwise.
     * @param app
     * @param hostingRecord
     * @param disableHiddenApiChecks
     * @param abiOverride
     */
    @GuardedBy("mService")
    boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
            boolean disableHiddenApiChecks, boolean mountExtStorageFull,
            String abiOverride) {
        
        try {
            
            ....
            int uid = app.uid;//1
            int[] gids = null;
            int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
            if (!app.isolated) {
               ......

                /*
                 *添加共享的应用程序和配置文件GID,以便应用程序可以共享 某些资源(如共享库)并访问用户范围的资源
                 */
                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)); //2
                .......
            }
            ......
            final String entryPoint = "android.app.ActivityThread";//3

            return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
                    runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
                    startTime);//4
        } catch (RuntimeException e) {
           .......
        }
    }
    
    
    boolean startProcessLocked(HostingRecord hostingRecord,
            String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
            long startTime) {
        
        .......

        if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
            if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
                    "Posting procStart msg for " + app.toShortString());
            mService.mProcStartHandler.post(() -> {
                try {
                    final Process.ProcessStartResult startResult = startProcess(app.hostingRecord,
                            entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal,
                            app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime);//5
                    synchronized (mService) {
                        handleProcessStartedLocked(app, startResult, startSeq);
                    }
                } catch (RuntimeException e) {
                   .....
            });
            return true;
        } else {
            try {
                final Process.ProcessStartResult startResult = startProcess(hostingRecord,
                        entryPoint, app,
                        uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
                        invokeWith, startTime);//6
                handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
                        startSeq, false);
            } catch (RuntimeException e) {
              ........  
            }
            return app.pid > 0;
        }
    }
  • 由以上代码注释1处获取了应用程序的用户id,注释2出获取了用户组ID,为应用程序进程提供用户组资源访问权限,注释3处给entryPoint赋值为android.app.ActivityThread,先记住这个值,后续分析还会继续提起它;注释4处接着调用了startProcessLocked方法,在该方法中注释5和6最终都是调用了ProcessList类的startProcess方法,接着往下看

frameworks/base/services/core/java/com/android/server/am/ProcessList.java


/**
     * The currently running application zygotes.
     */
    final ProcessMap<AppZygote> mAppZygotes = new ProcessMap<AppZygote>();

    /**
     * The processes that are forked off an application zygote.
     */
    final ArrayMap<AppZygote, ArrayList<ProcessRecord>> mAppZygoteProcesses =
            new ArrayMap<AppZygote, ArrayList<ProcessRecord>>();

 private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
            long startTime) {
        try {
           .......
            final Process.ProcessStartResult startResult;
            if (hostingRecord.usesWebviewZygote()) {
                startResult = startWebView(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName,
                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});//1
            } else if (hostingRecord.usesAppZygote()) {
                final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);

                startResult = appZygote.getProcess().start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName,
                        /*useUsapPool=*/ false,
                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});//2
            } else {
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, app.info.packageName,
                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});//3
            }
            ....
            return startResult;
        } 
        ......
    }

  • 由以上代码,startProcess方法会根据当前启动的是什么进程处理不同的逻辑,注释1是启动webview进程,注释2处理用户AppZygote,而注释3处才是出路新创建的应用程序进程,也就是调用了Process类的start方法,Process是
    用于管理操作系统进程的工具类,接着看它的start方法

Process 处理启动参数到Zygote进程

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

/**
     * State associated with the zygote process.
     * @hide
     */
    public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess(); //1

    public static ProcessStartResult start(@NonNull final String processClass,
                                           @Nullable final String niceName,
                                           int uid, int gid, @Nullable int[] gids,
                                           int runtimeFlags,
                                           int mountExternal,
                                           int targetSdkVersion,
                                           @Nullable String seInfo,
                                           @NonNull String abi,
                                           @Nullable String instructionSet,
                                           @Nullable String appDataDir,
                                           @Nullable String invokeWith,
                                           @Nullable String packageName,
                                           @Nullable String[] zygoteArgs) {
        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    /*useUsapPool=*/ true, zygoteArgs);//2
    }

  • 由以上代码,结合注释1和注释2则调用了ZygoteProcess类的start方法,ZygoteProcess保持与Zygote 的通信状态。 此类负责对Zygote 打开套接字,并代表Porcess启动进程。接着看到ZygoteProcess类的start方法

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

 public final Process.ProcessStartResult start(@NonNull final String processClass,
                                                  final String niceName,
                                                  int uid, int gid, @Nullable int[] gids,
                                                  int runtimeFlags, int mountExternal,
                                                  int targetSdkVersion,
                                                  @Nullable String seInfo,
                                                  @NonNull String abi,
                                                  @Nullable String instructionSet,
                                                  @Nullable String appDataDir,
                                                  @Nullable String invokeWith,
                                                  @Nullable String packageName,
                                                  boolean useUsapPool,
                                                  @Nullable String[] zygoteArgs) {
        .....
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                    packageName, useUsapPool, zygoteArgs);//1
        }
        .....
    }
  • 由以上代码注释1,又调用了ZygoteProcess类的start方法,接着往下看

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

private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
                                                      @Nullable final String niceName,
                                                      final int uid, final int gid,
                                                      @Nullable final int[] gids,
                                                      int runtimeFlags, int mountExternal,
                                                      int targetSdkVersion,
                                                      @Nullable String seInfo,
                                                      @NonNull String abi,
                                                      @Nullable String instructionSet,
                                                      @Nullable String appDataDir,
                                                      @Nullable String invokeWith,
                                                      boolean startChildZygote,
                                                      @Nullable String packageName,
                                                      boolean useUsapPool,
                                                      @Nullable String[] extraArgs)
                                                      throws ZygoteStartFailedEx {
        ArrayList<String> argsForZygote = new ArrayList<>();//1

        // --runtime-args, --setuid=, --setgid=,
        // and --setgroups= must go first
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        argsForZygote.add("--runtime-flags=" + runtimeFlags);
        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");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_FULL) {
            argsForZygote.add("--mount-external-full");
        }

        .......
        synchronized(mLock) {
            // The USAP pool can not be used if the application will not use the systems graphics
            // driver.  If that driver is requested use the Zygote application start path.
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                              useUsapPool,
                                              argsForZygote);//2
        }
    }
  • 由以上代码,注释1处创建了一个集合argsForZygote用来保存启动应用程序进程参数,接着又调用了zygoteSendArgsAndGetResult方法,而该方法第一个参数又调用了openZygoteSocketIfNeeded方法

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

private Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, boolean useUsapPool, @NonNull ArrayList<String> args)
            throws ZygoteStartFailedEx {
       .......

        if (useUsapPool && mUsapPoolEnabled && canAttemptUsap(args)) {
            try {
                return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);//1
            } catch (IOException ex) {
                // If there was an IOException using the USAP pool we will log the error and
                // attempt to start the process through the Zygote.
                Log.e(LOG_TAG, "IO Exception while communicating with USAP pool - "
                        + ex.getMessage());
            }
        }

        return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);//2
    }
    
    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        try {
            attemptConnectionToPrimaryZygote();//3

            if (primaryZygoteState.matches(abi)) {
                return primaryZygoteState;
            }

            if (mZygoteSecondarySocketAddress != null) {
                // The primary zygote didn't match. Try the secondary.
                attemptConnectionToSecondaryZygote();//4

                if (secondaryZygoteState.matches(abi)) {
                    return secondaryZygoteState;
                }
            }
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
        }

        throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
    }
  • 由以上代码,注释1处和注释2都传入了zygoteState,它代表的是ZygoteState类,它是ZygoteProcess静态内部类,保存了与 Zygote 进行通信的状态,而它的返回是由openZygoteSocketIfNeeded方法处理的,所以看到注释3和注释4分别调用了attemptConnectionToPrimaryZygote方法和attemptConnectionToSecondaryZygote方法,这和Zygote进程启动加载的配置文件有关,这里就不展开了,两个方法逻辑基本相同,直接看到其中一个attemptConnectionToPrimaryZygote方法

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

 /**
     * Creates a ZygoteState for the primary zygote if it doesn't exist or has been disconnected.
     */
    @GuardedBy("mLock")
    private void attemptConnectionToPrimaryZygote() throws IOException {
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            primaryZygoteState =
                    ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);//1

            maybeSetApiBlacklistExemptions(primaryZygoteState, false);
            maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
            maybeSetHiddenApiAccessStatslogSampleRate(primaryZygoteState);
        }
    }
  • 由注释1调用ZygoteState的connect方法来打开Socket连接,mZygoteSocketAddress则是名称为zygote的 Socket 服务

ActivityManagerService请求Zygote启动应用程序进程时序图

  • 本小节最后还是通过时序图来对上面的步骤进行回顾
AMS请求Zygote启动应用程序进程.jpg

Zygote启动应用程序进程

  • 经过上一小节分析,AMS最终是通过Socket方式进程间通信请求到了Zygote进程。Zygote英文为受精卵的意思,它启动过程创建了Android 虚拟机,其他应用程序进程则通过fork复制Zygote来创建应用程序进程,比如AMS服务所在的SystemServer进程,关于Zygote进程进程的启动过程细节又是另一部分内容了,本文则先只分析应用程序进程启动的过程,接下来从ZygoteInit的main方法开始

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

 @UnsupportedAppUsage
    public static void main(String argv[]) {
        .....
        Runnable caller;//1
        try {
            ........

            boolean startSystemServer = false;//2
            String zygoteSocketName = "zygote";//3
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {//4
                    startSystemServer = true;
                } 
                .......
            }

            final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
            
            ......
            Zygote.initNativeState(isPrimaryZygote);//5
            
            .....
            zygoteServer = new ZygoteServer(isPrimaryZygote);//6

            if (startSystemServer) { 
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); //7
            }

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);//8
        } 
        
        .......

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

由以上是缩短精简的ZygoteInit的main方法,注释1处创建了一个Runnable类型的请求对象代表此次请求Zygote获取应用进程的对象;结合注释2、4和7如果是Android系统启动过程,则会启动核心进程SystemServer,否则是启动其他应用程序进程,注释3出设置Socket连接名称为zygote,注释5出则初始化了Zygote的状态环境,包括支持套接字的环境,安全环境等,同时也包括Socket连接的名称为zygote;注释6创建了ZygoteServer对象,它可以理解为Zygote支持Socket进程通信的服务端,而在注释8的 runSelectLoop 方法则是Zygote进程等待接收AMS请求启动应用程序进程的关键方法,注释9先放着,接着往下看

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

Runnable runSelectLoop(String abiList) {
        ......
        while (true) {

            while (--pollIndex >= 0) {
                if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                    continue;
                }

                if (pollIndex == 0) {
                    // Zygote server socket

                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    socketFDs.add(newPeer.getFileDescriptor());

                } else if (pollIndex < usapPoolEventFDIndex) {
                    // Session socket accepted from the Zygote server socket  从Zygote服务器套接字接受会话套接字

                    try {
                        ZygoteConnection connection = peers.get(pollIndex);
                        final Runnable command = connection.processOneCommand(this); //1

                        ......
                            return command;
                        } 
        .......                
    }
  • 由以上代码,通过一个死循环等待接收请求,注释1处则调用了ZygoteConnection的processOneCommand方法,接着往下看

获取应用程序进程

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

/**
     * Reads one start command from the command socket. If successful, a child is forked and a
     * {@code Runnable} that calls the childs main method (or equivalent) is returned in the child
     * process. {@code null} is always returned in the parent process (the zygote).
     *
     * If the client closes the socket, an {@code EOF} condition is set, which callers can test
     * for by calling {@code ZygoteConnection.isClosedByPeer}.
     */
    Runnable processOneCommand(ZygoteServer zygoteServer) {
        String args[];
        ZygoteArguments parsedArgs = null;
        FileDescriptor[] descriptors;

        try {
            args = Zygote.readArgumentList(mSocketReader);//1
           ....
        } 
        
        ......

        pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
                parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
                parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion); //2

        try {
            if (pid == 0) { //3
                // in child
                zygoteServer.setForkChild();

                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;

                return handleChildProc(parsedArgs, descriptors, childPipeFd,
                        parsedArgs.mStartChildZygote);
            } 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;
            }
        } 
        ......
    }
  • 由以上代码注释1处获取了启动应用程序进程的参数,看到注释2处,直接调用了Zygote类的forkAndSpecialize方法

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

    /**
     * Forks a new VM instance.  The current VM must have been started
     * @return 0 if this is the child, pid of the child
     * if this is the parent, or -1 on error.
     */
    public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
            int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
            int targetSdkVersion) {
        ZygoteHooks.preFork();
        // Resets nice priority for zygote process.
        resetNicePriority();
        int pid = nativeForkAndSpecialize(
                uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                fdsToIgnore, startChildZygote, instructionSet, appDataDir);//1
        return pid;
    }
  • 由以上代码注释1处,通过Native方法nativeForkAndSpecialize与底层通信复制fork出应用即将要启动的应用程序进程,本文则关注大致流程,底层Native实现则不再继续展开,有兴趣朋友可以继续跟进frameworks/base/core/jni/com_android_internal_os_Zygote.cpp查看。根据forkAndSpecialize方法的注释也可以明白,该方法返回0则为child,也就是应用程序进程,-1则为父进程,所以这里再次回到ZygoteConnection的processOneCommand方法,启动的是应用程序进程,则在注释3出pid=0 此时已经处于应用程序进程了,接着继续调用ZygoteConnection的
    handleChildProc方法

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

    private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
            FileDescriptor pipeFd, boolean isZygote) {
        ..........
        } else {
            if (!isZygote) {
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */); //1
            } else {
                return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            }
        }
    }
  • 由以上源码,启动的是应用程序进程则会走到注释1处调用ZygoteInit类的zygoteInit方法

创建应用程序的ActivityThread

frameworks/base/core/java/com/android/internal/os/ZygoteInit.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出的Native方法会创建当前应用程序进程的Binder线程池,则当前应用程序就拥有了Binder通信的能力,注释2处接着调用了RuntimeInit的applicationInit方法

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

protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        ......

        final Arguments args = new Arguments(argv); //1
        ......
        return findStaticMain(args.startClass, args.startArgs, classLoader);2
    }
  • 由以上代码,注释1处处理AMS请求中传递过来的参数,这其中就包括android.app.ActivityThread,也就是注释2处args.startClass代表的值,接着继续看findStaticMain方法

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

 protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);//1
        } 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 });//2
        } 
        ......

        /*
         * 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);
    }
  • 由以上代码,注释1处反射获取了android.app.ActivityThread,也就是应用程序进程的ActivityThread,注释2处获取了ActivityThread的main方法,然后返回了Runnable对象为MethodAndArgsCaller

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

/**
     * Helper class which holds a method and arguments and can call them. This is used as part of
     * a trampoline to get rid of the initial process setup stack frames.
     */
    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 {
                mMethod.invoke(null, new Object[] { mArgs }); //1
            } 
            ...
        }
    }
  • 由以上代码,注释1处代表应用程序进程ActivityThread的main方法,结合本小节开头的从ZygoteInit的main方法的注释9,目前已经处于应用程序进程,则会调用Runnable类型caller的run方法,也就是MethodAndArgsCaller的run方法,由以上代码注释1处,则会调用ActivityThread的main方法,而ActivityThread作为每个应程序主线程的管理类,到此,应用程序进程启动完成,接着上一篇文章,当ATMS与应用程序Binder通信通过IApplicationThread为ActivityThread的内部类,然后调用ActivityThread的performLaunchActivity方法来启动Activity

Zygote启动应用程序进程时序图

  • 本小节最后还是通过时序图来对上面的步骤进行回顾
Zygote启动应用程序进程.jpg

总结

启动过程涉及的进程

应用程序启动过程各个进程间调用关系图.jpg

参考

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345