Android应用进程的创建过程

基于Android 7.0源码分析

以Launcher点击应用启动应用为例

ActivityManagerService(system_server)请求Zygote创建应用进程的过程

当运行应用时,如果应用进程还没有创建,ActivityManagerService会请求Zygotefork进程,下面从ActivityManagerServicestartProcessLocked()开始分析。

final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        String hostingType, ComponentName hostingName, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    // keepIfLarge为true,knownToBeDead为true,intentFlags为0,allowWhileBooting为false
    // isolated为false
    return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
            hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
            null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
            null /* crashHandler */);
}

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
        boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
        boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
        String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
    long startTime = SystemClock.elapsedRealtime();
    ProcessRecord app;
    // isolated通常为false,与安全相关
    if (!isolated) {
        // 查找ProcessRecord,非isolated进程,可以重用先前的ProcessRecord
        app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
        checkTime(startTime, "startProcess: after getProcessRecord");
        if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
            // If we are in the background, then check to see if this process
            // is bad.  If so, we will just silently fail.
            // 检查是否是经常crash的应用
            if (mAppErrors.isBadProcessLocked(info)) {
                if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
                        + "/" + info.processName);
                return null;
            }
        } else {
            // When the user is explicitly starting a process, then clear its
            // crash count so that we won't make it bad until they see at
            // least one crash dialog again, and make the process good again
            // if it had been bad.
            if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
                    + "/" + info.processName);
            // 清理进程crash信息
            mAppErrors.resetProcessCrashTimeLocked(info);
            if (mAppErrors.isBadProcessLocked(info)) {
                EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                        UserHandle.getUserId(info.uid), info.uid,
                        info.processName);
                mAppErrors.clearBadProcessLocked(info);
                if (app != null) {
                    app.bad = false;
                }
            }
        }
    } else {
        // If this is an isolated process, it can't re-use an existing process.
        // isolated进程不能重用ProcessRecord
        app = null;
    }
    // app launch boost for big.little configurations
    // use cpusets to migrate freshly launched tasks to big cores
    // 对于大小核架构,使用cpuset,将前台任务迁移到大核上
    nativeMigrateToBoost();
    mIsBoosted = true;
    mBoostStartTime = SystemClock.uptimeMillis();
    // 设置Boost超时取消
    Message msg = mHandler.obtainMessage(APP_BOOST_DEACTIVATE_MSG);
    mHandler.sendMessageDelayed(msg, APP_BOOST_MESSAGE_DELAY);
    ......
    if (app != null && app.pid > 0) {
        if ((!knownToBeDead && !app.killed) || app.thread == null) {
            // 应用进程已经运行或者即将运行
            // We already have the app running, or are waiting for it to
            // come up (we have a pid but not yet its thread), so keep it.
            if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
            // If this is a new package in the process, add the package to the list
            app.addPackage(info.packageName, info.versionCode, mProcessStats);
            checkTime(startTime, "startProcess: done, added package to proc");
            return app;
        }
        // An application record is attached to a previous process,
        // clean it up now.
        if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app);
        // ProcessRecord关联到先前的进程,清理
        checkTime(startTime, "startProcess: bad proc running, killing");
        killProcessGroup(app.uid, app.pid);
        handleAppDiedLocked(app, true, true);
        checkTime(startTime, "startProcess: done killing old proc");
    }
    ......
    if (app == null) {
        checkTime(startTime, "startProcess: creating new process record");
        // 创建新的ProcessRecord
        app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
        if (app == null) {
            Slog.w(TAG, "Failed making new process record for "
                    + processName + "/" + info.uid + " isolated=" + isolated);
            return null;
        }
        // 设置crashHandler
        app.crashHandler = crashHandler;
        checkTime(startTime, "startProcess: done creating new process record");
    } else {
        // If this is a new package in the process, add the package to the list
        app.addPackage(info.packageName, info.versionCode, mProcessStats);
        checkTime(startTime, "startProcess: added package to existing proc");
    }
    ......
    // 系统尚未准备好,暂缓启动进程,待启动进程添加到mProcessesOnHold
    if (!mProcessesReady
            && !isAllowedWhileBooting(info)
            && !allowWhileBooting) {
        if (!mProcessesOnHold.contains(app)) {
            mProcessesOnHold.add(app);
        }
        if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
                "System not ready, putting on hold: " + app);
        checkTime(startTime, "startProcess: returning with proc on hold");
        return app;
    }
    checkTime(startTime, "startProcess: stepping in to startProcess");
    // 启动应用进程
    startProcessLocked(
            app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
    checkTime(startTime, "startProcess: done starting proc!");
    return (app.pid != 0) ? app : null;
}
  • 注意ProcessRecord可被重用

下面继续看startProcessLocked()实现

private final void startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    long startTime = SystemClock.elapsedRealtime();
    if (app.pid > 0 && app.pid != MY_PID) {
        // 重用的ProcessRecord,pid > 0
        checkTime(startTime, "startProcess: removing from pids map");
        // 从pids map中移除,移除进程启动超时消息
        synchronized (mPidsSelfLocked) {
            mPidsSelfLocked.remove(app.pid);
            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
        }
        checkTime(startTime, "startProcess: done removing from pids map");
        // pid置0
        app.setPid(0);
    }
    mProcessesOnHold.remove(app);
    ......
    try {
        try {
            // 获取userId,通常为0
            final int userId = UserHandle.getUserId(app.uid);
            // 检查应用的package状态
            AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
        ......
        int debugFlags = 0;
        if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
            // 应用可调式
            debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
            // Also turn on CheckJNI for debuggable apps. It's quite
            // awkward to turn on otherwise.
            debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
        }
        // Run the app in safe mode if its manifest requests so or the
        // system is booted in safe mode.
        if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
            mSafeMode == true) {
            // 运行在安全模式
            debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
        }
        ......
        // abiOverride为null使用app的primaryCpuAbi
        String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
        if (requiredAbi == null) {
            // 如果requiredAbi为null,使用系统支持的CPUABI列表中的第一个
            requiredAbi = Build.SUPPORTED_ABIS[0];
        }
        String instructionSet = null;
        if (app.info.primaryCpuAbi != null) {
            // 查找CPUABI对应的指令集
            // armeabi => arm
            // armeabi-v7a => arm
            // arm64-v8a => arm64
            instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
        }
        // 进程所属额外的group ids
        app.gids = gids;
        app.requiredAbi = requiredAbi;
        app.instructionSet = instructionSet;
        ......
        boolean isActivityProcess = (entryPoint == null);
        // 设置进程入口,通常为"android.app.ActivityThread"
        if (entryPoint == null) entryPoint = "android.app.ActivityThread";
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                app.processName);
        checkTime(startTime, "startProcess: asking zygote to start proc");
        // 请求Zygote fork进程并等待Zygote发送进程启动结果
        Process.ProcessStartResult startResult = Process.start(entryPoint,
                app.processName, uid, uid, gids, debugFlags, mountExternal,
                app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                app.info.dataDir, entryPointArgs);
        checkTime(startTime, "startProcess: returned from zygote!");
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        if (app.isolated) {
            mBatteryStatsService.addIsolatedUid(app.uid, app.info.uid);
        }
        // 通知BatteryStatsService进程启动
        mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);
        checkTime(startTime, "startProcess: done updating battery stats");
        // AM_PROC_START事件log
        EventLog.writeEvent(EventLogTags.AM_PROC_START,
                UserHandle.getUserId(uid), startResult.pid, uid,
                app.processName, hostingType,
                hostingNameStr != null ? hostingNameStr : "");
        ......
        if (app.persistent) {
            // 记录Phone进程的pid
            Watchdog.getInstance().processStarted(app.processName, startResult.pid);
        }
        ......
        // 设置ProcessRecord新进程信息
        app.setPid(startResult.pid);
        app.usingWrapper = startResult.usingWrapper;
        app.removed = false;
        app.killed = false;
        app.killedByAm = false;
        checkTime(startTime, "startProcess: starting to update pids map");
        synchronized (mPidsSelfLocked) {
            this.mPidsSelfLocked.put(startResult.pid, app);
            if (isActivityProcess) {
                // 设置应用进程attach到ActivityManagerService的超时检测
                Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
                msg.obj = app;
                mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                        ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
            }
        }
        ......
    }
}

下面看Processstart()方法

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[] zygoteArgs) {
    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                debugFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        Log.e(LOG_TAG,
                "Starting VM process through Zygote failed");
        throw new RuntimeException(
                "Starting VM process through Zygote failed", ex);
    }
}
  • processClass 进程入口类名
  • niceName 进程名
  • uid 进程uid
  • gid 进程group id(通常等于uid)
  • gids 进程所属额外的group ids
  • debugFlags 进程调试标志位
  • targetSdkVersion 应用目标sdk
  • seInfo 进程的SELinux信息
  • abi 进程运行的abi
  • instructionSet 进程运行的指令集
  • appDataDir 应用的数据路径(/data/user/0/xxx)

下面看startViaZygote()的实现

private static 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[] extraArgs)
                              throws ZygoteStartFailedEx {
    synchronized(Process.class) {
        // 通过ArrayList传递启动参数给Zygote
        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);
        ......
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
}

// 如果还没有创建Socket,创建Socket用于与Zygote通信
// ZygoteState用于管理与Zygote通信的状态
// 通常在arm64系统中,通常primaryZygoteState与secondaryZygoteState分别对应
// 进程Zygote64与Zygote(取决于*.rc文件配置)
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    // 如果primaryZygoteState没有创建或已经关闭,创建它
    if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
        try {
            primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
        }
    }
    // 检查abi是否匹配primaryZygoteState
    if (primaryZygoteState.matches(abi)) {
        return primaryZygoteState;
    }
    // The primary zygote didn't match. Try the secondary.
    if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
        try {
        secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
        }
    }
    // 检查abi是否匹配secondaryZygoteState
    if (secondaryZygoteState.matches(abi)) {
        return secondaryZygoteState;
    }
    throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}

// 向Zygote进程(Zygote64/Zygote)发送参数列表,请求fork进程
private static ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, ArrayList<String> args)
        throws ZygoteStartFailedEx {
    try {
        final BufferedWriter writer = zygoteState.writer;
        final DataInputStream inputStream = zygoteState.inputStream;
        // 向Zygote发送参数的数目以及参数字符串
        writer.write(Integer.toString(args.size()));
        writer.newLine();
        int sz = args.size();
        for (int i = 0; i < sz; i++) {
            String arg = args.get(i);
            if (arg.indexOf('\n') >= 0) {
                throw new ZygoteStartFailedEx(
                        "embedded newlines not allowed");
            }
            writer.write(arg);
            writer.newLine();
        }
        writer.flush();

        // 读取Zygote发送结果,可能需要等待
        ProcessStartResult result = new ProcessStartResult();
        result.pid = inputStream.readInt();
        if (result.pid < 0) {
            throw new ZygoteStartFailedEx("fork() failed");
        }
        result.usingWrapper = inputStream.readBoolean();
        return result;
    } catch (IOException ex) {
        zygoteState.close();
        throw new ZygoteStartFailedEx(ex);
    }
}

下面看Zygote收到请求后,创建应用进程的过程。Zygote进程启动后,会调用runSelectLoop()等待客户端的连接请求,下面分析runSelectLoop()

public static void main(String argv[]) {
    // Mark zygote start. This ensures that thread creation will throw
    // an error.
    ZygoteHooks.startZygoteNoThreadCreation();
    try {
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
        ......
        // 运行runSelectLoop,等待客户端连接
        runSelectLoop(abiList);
        closeServerSocket();
    } catch (MethodAndArgsCaller caller) {
        // 子进程中调用MethodAndArgsCaller的run方法
        caller.run();
    } catch (RuntimeException ex) {
        Log.e(TAG, "Zygote died with exception", ex);
        closeServerSocket();
        throw ex;
    }
}

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    fds.add(sServerSocket.getFileDescriptor());
    peers.add(null);

    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            pollFds[i].events = (short) POLLIN;
        }
        try {
            // 监听文件描述符集pollFds
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            throw new RuntimeException("poll failed", ex);
        }
        for (int i = pollFds.length - 1; i >= 0; --i) {
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue;
            }
            if (i == 0) {
                // 接收客户端的连接请求,创建ZygoteConnection
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                // 读取、处理客户端请求
                ne = peers.get(i).runOnce();
                if (done) {
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}

// 在子进程中会抛出ZygoteInit.MethodAndArgsCaller
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;
    try {
        // 读取客户端发送的参数列表
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        Log.w(TAG, "IOException on command socket " + ex.getMessage());
        closeSocket();
        return true;
    }
    ......
    try {
        // 解析参数列表
        parsedArgs = new Arguments(args);
        if (parsedArgs.abiListQuery) {
            // 处理客户端查询abiList请求(客户端socket创建时)
            return handleAbiListQuery();
        }
        ......
        // 安全检查
        applyUidSecurityPolicy(parsedArgs, peer);
        applyInvokeWithSecurityPolicy(parsedArgs, peer);
        applyDebuggerSystemProperty(parsedArgs);
        applyInvokeWithSystemProperty(parsedArgs);
        ......
        // 避免子进程文件描述符泄露,需要关闭Zygote socket文件描述符
        int [] fdsToClose = { -1, -1 };
        FileDescriptor fd = mSocket.getFileDescriptor();
        if (fd != null) {
            fdsToClose[0] = fd.getInt$();
        }
        fd = ZygoteInit.getServerSocketFileDescriptor();
        if (fd != null) {
            fdsToClose[1] = fd.getInt$();
        }
        fd = null;
        // fork进程
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
    }
    
    try {
        if (pid == 0) {
            // in child
            // 子进程中执行
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            // 处理子进程fork后的设置,见下一节
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
            // should never get here, the child is expected to either
            // throw ZygoteInit.MethodAndArgsCaller or exec().
            return true;
        } else {
            // in parent...pid of < 0 means failure
            // Zygote进程中执行
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

下面看forkAndSpecialize的实现

public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
      int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
      String instructionSet, String appDataDir) {
    // fork之前的准备工作
    VM_HOOKS.preFork();
    int pid = nativeForkAndSpecialize(
              uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
              instructionSet, appDataDir);
    // Enable tracing as soon as possible for the child process.
    if (pid == 0) {
        // 在子进程中使能trace
        Trace.setTracingEnabled(true);
        // Note that this event ends at the end of handleChildProc,
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
    }
    // fork之后的工作
    VM_HOOKS.postForkCommon();
    return pid;
}

public void preFork() {
    // 停止4个守护线程
    Daemons.stop();
    // 等待守护线程结束
    waitUntilAllThreadsStopped();
    // 整理heap,如果有zygote heap基本上没有工作
    token = nativePreFork();
}

public static void stop() {
    HeapTaskDaemon.INSTANCE.stop();
    ReferenceQueueDaemon.INSTANCE.stop();
    FinalizerDaemon.INSTANCE.stop();
    FinalizerWatchdogDaemon.INSTANCE.stop();
}

public void postForkCommon() {
    // 启动4个守护线程
    Daemons.start();
}

这里介绍下4个守护线程:

  • HeapTaskDaemon
    • 用于处理GC tasks,包括Heap裁减,Heap垃圾回收器切换,Heap GC
  • ReferenceQueueDaemon
    • 当Reference关联的对象被GC回收时,GC将Reference添加到静态链表(ReferenceQueue.unenqueued)中,ReferenceQueueDaemon负责将静态链表中的Reference添加到关联的ReferenceQueue中
  • FinalizerDaemon
    • 执行对象的finalize方法,对于FinalizerDaemon的执行过程以后讨论
  • FinalizerWatchdogDaemon
    • 监视FinalizerDaemon

下面看nativeForkAndSpecialize的实现

static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
        jint debug_flags, jobjectArray rlimits,
        jint mount_external, jstring se_info, jstring se_name,
        jintArray fdsToClose, jstring instructionSet, jstring appDataDir) {
    jlong capabilities = 0;
    ......
    return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
            rlimits, capabilities, capabilities, mount_external, se_info,
            se_name, false, fdsToClose, instructionSet, appDataDir);
}

static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                     jint debug_flags, jobjectArray javaRlimits,
                                     jlong permittedCapabilities, jlong effectiveCapabilities,
                                     jint mount_external,
                                     jstring java_se_info, jstring java_se_name,
                                     bool is_system_server, jintArray fdsToClose,
                                     jstring instructionSet, jstring dataDir) {

  SetSigChldHandler();
  ......
  // fork进程
  pid_t pid = fork();

  if (pid == 0) {
    // 子进程
    // The child process.
    gMallocLeakZygoteChild = 1;

    // Clean up any descriptors which must be closed immediately
    // 关闭继承自zygote的socket文件描述符
    DetachDescriptors(env, fdsToClose);
    ......
    if (!is_system_server) {
        // 创建进程组
        int rc = createProcessGroup(uid, getpid());
        if (rc != 0) {
            if (rc == -EROFS) {
                ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
            } else {
                ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc));
            }
        }
    }
    // 设置进程所属额外的groups
    SetGids(env, javaGids);
    // 设置资源限制
    SetRLimits(env, javaRlimits);

    // 通常不使用native bridge
    // native bridge用于运行带有与系统不同的处理器架构native库的应用
    if (use_native_bridge) {
      ScopedUtfChars isa_string(env, instructionSet);
      ScopedUtfChars data_dir(env, dataDir);
      android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str());
    }

    // 设置real GID/effective GID/saved set-user-ID GID
    int rc = setresgid(gid, gid, gid);
    if (rc == -1) {
      ALOGE("setresgid(%d) failed: %s", gid, strerror(errno));
      RuntimeAbort(env, __LINE__, "setresgid failed");
    }
    // 设置real UID/effective UID/saved set-user-ID UID
    rc = setresuid(uid, uid, uid);
    if (rc == -1) {
      ALOGE("setresuid(%d) failed: %s", uid, strerror(errno));
      RuntimeAbort(env, __LINE__, "setresuid failed");
    }

    if (NeedsNoRandomizeWorkaround()) {
        // 针对低版本kernel,弥补ASLR(地址空间布局随机化)的缺失
        // Work around ARM kernel ASLR lossage (http://b/5817320).
        int old_personality = personality(0xffffffff);
        int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
        if (new_personality == -1) {
            ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
        }
    }
    // 设置权限
    SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
    // 设置调度策略(SP_DEFAULT)
    SetSchedulerPolicy(env);
    ......
    // 设置Selinux策略
    rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
    ......
    if (se_info_c_str != NULL) {
      // 设置进程名
      SetThreadName(se_name_c_str);
    }

    delete se_info;
    delete se_name;
    // 取消SIGCHLD信号处理
    UnsetSigChldHandler();
    // 调用Zygote的callPostForkChildHooks方法
    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
                              is_system_server, instructionSet);
    if (env->ExceptionCheck()) {
      RuntimeAbort(env, __LINE__, "Error calling post fork hooks.");
    }
  } else if (pid > 0) {
    // the parent process

#ifdef ENABLE_SCHED_BOOST
    // unset scheduler knob
    SetForkLoad(false);
#endif

  }
  return pid;
}

下面看ZygotecallPostForkChildHooks的实现

private static void callPostForkChildHooks(int debugFlags, boolean isSystemServer,
        String instructionSet) {
    VM_HOOKS.postForkChild(debugFlags, isSystemServer, instructionSet);
}

public void postForkChild(int debugFlags, boolean isSystemServer, String instructionSet) {
    // 在Zygote fork之后的子进程中调用
    nativePostForkChild(token, debugFlags, isSystemServer, instructionSet);
    Math.setRandomSeedInternal(System.currentTimeMillis());
}

nativePostForkChild()是个native方法,下面看它的实现。

static void ZygoteHooks_nativePostForkChild(JNIEnv* env,
                                            jclass,
                                            jlong token,
                                            jint debug_flags,
                                            jboolean is_system_server,
                                            jstring instruction_set) {
  Thread* thread = reinterpret_cast<Thread*>(token);
  // Our system thread ID, etc, has changed so reset Thread state.
  thread->InitAfterFork();
  EnableDebugFeatures(debug_flags);
  ......
  if (instruction_set != nullptr && !is_system_server) {
    // 指令集不为空且非system_server  
    ScopedUtfChars isa_string(env, instruction_set);
    InstructionSet isa = GetInstructionSetFromString(isa_string.c_str());
    Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload;
    if (isa != kNone && isa != kRuntimeISA) {
      action = Runtime::NativeBridgeAction::kInitialize;
    }
    // 设置heap、创建Jit等
    Runtime::Current()->InitNonZygoteOrPostFork(
        env, is_system_server, action, isa_string.c_str());
  } else {
    Runtime::Current()->InitNonZygoteOrPostFork(
        env, is_system_server, Runtime::NativeBridgeAction::kUnload, nullptr);
  }
}

void Runtime::InitNonZygoteOrPostFork(
    JNIEnv* env, bool is_system_server, NativeBridgeAction action, const char* isa) {
  is_zygote_ = false;

  // 通常is_native_bridge_loaded_为false, See ro.dalvik.vm.native.bridge属性
  if (is_native_bridge_loaded_) {
    switch (action) {
      case NativeBridgeAction::kUnload:
        UnloadNativeBridge();
        is_native_bridge_loaded_ = false;
        break;

      case NativeBridgeAction::kInitialize:
        InitializeNativeBridge(env, isa);
        break;
    }
  }

  // Create the thread pools.
  heap_->CreateThreadPool();
  // Reset the gc performance data at zygote fork so that the GCs
  // before fork aren't attributed to an app.
  // 重置GC性能数据
  heap_->ResetGcPerformanceInfo();

  if (!is_system_server &&
      !safe_mode_ &&
      (jit_options_->UseJitCompilation() || jit_options_->GetSaveProfilingInfo()) &&
      jit_.get() == nullptr) {
    // Note that when running ART standalone (not zygote, nor zygote fork),
    // the jit may have already been created.
    // 创建Jit
    CreateJit();
  }
  // 启动Signal Catcher Thread
  StartSignalCatcher();

  // Start the JDWP thread. If the command-line debugger flags specified "suspend=y",
  // this will pause the runtime, so we probably want this to come last.
  Dbg::StartJdwp();
}

至此,应用进程基本创建完成,下面看应用进程创建后设置的过程。

应用进程创建后设置的过程

回到ZygoteConnectionrunOnce中,下面分析子进程fork后的设置,也就是handleChildProc的实现。

private void handleChildProc(Arguments parsedArgs,
        FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
        throws ZygoteInit.MethodAndArgsCaller {
    /**
     * By the time we get here, the native code has closed the two actual Zygote
     * socket connections, and substituted /dev/null in their place.  The LocalSocket
     * objects still need to be closed properly.
     */
    // 关闭与连接关联的socket
    closeSocket();
    // 关闭清理Zygote socket
    ZygoteInit.closeServerSocket();
    ......
    // End of the postFork event.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    // 这里invokeWith为null
    if (parsedArgs.invokeWith != null) {
        WrapperInit.execApplication(parsedArgs.invokeWith,
                parsedArgs.niceName, parsedArgs.targetSdkVersion,
                VMRuntime.getCurrentInstructionSet(),
                pipeFd, parsedArgs.remainingArgs);
    } else {
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                parsedArgs.remainingArgs, null /* classLoader */);
    }
}

下面看RuntimeInitzygoteInit方法的实现

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
    // System.out重定向到Android log
    redirectLogStreams();
    // 设置未捕获异常处理,Logger log写入Android log等
    commonInit();
    // 支持Binder通信
    nativeZygoteInit();
    applicationInit(targetSdkVersion, argv, classLoader);
}

在Android应用中使用System.out以及Logger打印log,通过logcat也能看到。

下面看applicationInit的实现

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    // 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.
    // heap目标利用率设置
    VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
    VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
    final Arguments args;
    try {
        args = new Arguments(argv);
    } catch (IllegalArgumentException ex) {
        Slog.e(TAG, ex.getMessage());
        // let the process exit
        return;
    }
    // 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
    // 调用ActivityThread的main方法
    invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl;
    try {
        // 获取ActivityThread类对象
        cl = Class.forName(className, true, classLoader);
    } 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();
    // main方法必须是public static
    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.
     */
    // 为了进程启动时清理栈帧,抛出MethodAndArgsCaller,在ZygoteInit.main方法中捕获处理
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

回到ZygoteInitmain方法中。

public static void main(String argv[]) {
    // Mark zygote start. This ensures that thread creation will throw
    // an error.
    ZygoteHooks.startZygoteNoThreadCreation();
    try {
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
        ......
        runSelectLoop(abiList);
        closeServerSocket();
    } catch (MethodAndArgsCaller caller) {
        // 调用MethodAndArgsCaller的run方法
        caller.run();
    } catch (RuntimeException ex) {
        Log.e(TAG, "Zygote died with exception", ex);
        closeServerSocket();
        throw ex;
    }
}

public static class MethodAndArgsCaller extends Exception
        implements Runnable {
    ......
    public void run() {
        try {
            // 调用ActivityThread的main方法
            mMethod.invoke(null, new Object[] { mArgs });
        } 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);
        }
    }
}

对于Android应用进程的启动过程,这里分析到ActivityThreadmain方法,对于后续流程暂不讨论。

小结

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

推荐阅读更多精彩内容