目录
前言
今天简单的记录一下App进程的启动过程。
继之前startActivity的源码分析(《》和《》)中的进程启动是一带而过的,聪明的你会发现,进程启动的大部分跟《》重合了。
正文
回到《》文章末尾的startProcessLocked()。
ActivityManagerService.java
PS: 大部分内容都略了
startProcessLocked()
- @GuardedBy("this")
- 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) {
- //略
- final boolean success = startProcessLocked(app, hostingType, hostingNameStr, abiOverride);
- //略
- }
startProcessLocked()
- @GuardedBy("this")
- private final boolean startProcessLocked(ProcessRecord app,
- String hostingType, String hostingNameStr, String abiOverride) {
- return startProcessLocked(app, hostingType, hostingNameStr,
- false /* disableHiddenApiChecks */, abiOverride);
- }
startProcessLocked()
- @GuardedBy("this")
- private final boolean startProcessLocked(ProcessRecord app, String hostingType,
- String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
- //日志显示,前面几个startProcessLocked()会被调用2次
- //第一次app.pendingStart=false;第二次app.pendingStart=true;
- //因此第二次直接返回
- if (app.pendingStart) {
- return true;
- }
- //略
- try {
- try {
- final int userId = UserHandle.getUserId(app.uid);
- //PackageManagerService.java中检测
- //(1)判断是否存在(2)判断是否安装等,如果有问题就抛出异常
- AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
- //略
- //false
- if (!app.isolated) {
- }
- //略
- //注意,这里传入了android.app.ActivityThread
- final String entryPoint = "android.app.ActivityThread";
- //进入下一个startProcessLocked()
- return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
- runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
- startTime);
- } catch (RuntimeException e) {
- forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false,
- false, true, false, false, UserHandle.getUserId(app.userId), "start failure");
- return false;
- }
- }
这里有个重点,参数中传入了entryPoint,而entryPoint是
- final String entryPoint = "android.app.ActivityThread";
fork出子进程后会启动android.app.ActivityThread
startProcessLocked()
- @GuardedBy("this")
- private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,
- ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
- String seInfo, String requiredAbi, String instructionSet, String invokeWith,
- long startTime) {
- //略
- //异步启动 true
- if (mConstants.FLAG_PROCESS_START_ASYNC) {
- //使用Handler的post,也就是异步执行。
- //会先返回return
- mProcStartHandler.post(() -> {
- try {
- synchronized (ActivityManagerService.this) {
- final String reason = isProcStartValidLocked(app, startSeq);
- //reason为null
- if (reason != null) {
- app.pendingStart = false;
- return;
- }
- app.usingWrapper = invokeWith != null
- || SystemProperties.get("wrap." + app.processName) != null;
- mPendingStarts.put(startSeq, app);
- }
- //启动进程startProcess,关键点
- final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
- app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
- requiredAbi, instructionSet, invokeWith, app.startTime);
- synchronized (ActivityManagerService.this) {
- handleProcessStartedLocked(app, startResult, startSeq);
- }
- } catch (RuntimeException e) {
- synchronized (ActivityManagerService.this) {
- mPendingStarts.remove(startSeq);
- app.pendingStart = false;
- forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
- false, false, true, false, false,
- UserHandle.getUserId(app.userId), "start failure");
- }
- }
- });
- return true;
- } else {
- try {
- final ProcessStartResult startResult = startProcess(hostingType, entryPoint, app,
- uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
- invokeWith, startTime);
- handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
- startSeq, false);
- } catch (RuntimeException e) {
- app.pendingStart = false;
- forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
- false, false, true, false, false,
- UserHandle.getUserId(app.userId), "start failure");
- }
- return app.pid > 0;
- }
- }
startProcess()
- private ProcessStartResult startProcess(String hostingType, String entryPoint,
- ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
- String seInfo, String requiredAbi, String instructionSet, String invokeWith,
- long startTime) {
- try {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
- app.processName);
- //hostingType这里是启动activity,
- if (hostingType.equals("webview_service")) {
- startResult = startWebView(entryPoint,
- app.processName, uid, uid, gids, runtimeFlags, mountExternal,
- app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
- app.info.dataDir, null,
- new String[] {PROC_START_SEQ_IDENT + app.startSeq});
- } else {
- //走这里,进入了Process
- startResult = Process.start(entryPoint,
- app.processName, uid, uid, gids, runtimeFlags, mountExternal,
- app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
- app.info.dataDir, invokeWith,
- new String[] {PROC_START_SEQ_IDENT + app.startSeq});
- }
- checkTime(startTime, "startProcess: returned from zygote!");
- return startResult;
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- }
- }
Process.java
start()
- public static final ProcessStartResult start(final String processClass,
- final String niceName,
- int uid, int gid, int[] gids,
- int runtimeFlags, int mountExternal,
- int targetSdkVersion,
- String seInfo,
- String abi,
- String instructionSet,
- String appDataDir,
- String invokeWith,
- String[] zygoteArgs) {
- return zygoteProcess.start(processClass, niceName, uid, gid, gids,
- runtimeFlags, mountExternal, targetSdkVersion, seInfo,
- abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
- }
ZygoteProcess.java
start()
- public final Process.ProcessStartResult start(final String processClass,
- final String niceName,
- int uid, int gid, int[] gids,
- int runtimeFlags, int mountExternal,
- int targetSdkVersion,
- String seInfo,
- String abi,
- String instructionSet,
- String appDataDir,
- String invokeWith,
- String[] zygoteArgs) {
- try {
- return startViaZygote(processClass, niceName, uid, gid, gids,
- runtimeFlags, mountExternal, targetSdkVersion, seInfo,
- abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
- zygoteArgs);
- } catch (ZygoteStartFailedEx ex) {
- throw new RuntimeException(
- "Starting VM process through Zygote failed", ex);
- }
- }
startViaZygote()
- private Process.ProcessStartResult startViaZygote(final String processClass,
- final String niceName,
- final int uid, final int gid,
- final int[] gids,
- int runtimeFlags, int mountExternal,
- int targetSdkVersion,
- String seInfo,
- String abi,
- String instructionSet,
- String appDataDir,
- String invokeWith,
- boolean startChildZygote,
- String[] extraArgs)
- throws ZygoteStartFailedEx {
- ArrayList<String> argsForZygote = new ArrayList<String>();
- //argsForZygote保存相关信息,进程uid,gid等等
- 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");
- }
- argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
- 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());
- }
- //niceName是应用包名
- 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);
- }
- //invokeWith为null
- if (invokeWith != null) {
- argsForZygote.add("--invoke-with");
- argsForZygote.add(invokeWith);
- }
- //startChildZygote = false
- if (startChildZygote) {
- argsForZygote.add("--start-child-zygote");
- }
- argsForZygote.add(processClass);
- if (extraArgs != null) {
- for (String arg : extraArgs) {
- argsForZygote.add(arg);
- }
- }
- synchronized(mLock) {
- //abi是平台架构类型,比如arm64-v8a,x86等,我这里是arm64-v8a
- //[重]openZygoteSocketIfNeeded()
- //[重]zygoteSendArgsAndGetResult()进程跟Zygote数据传输和读取返回结果
- return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
- }
- }
openZygoteSocketIfNeeded()
- @GuardedBy("mLock")
- private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
- Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");
- //primaryZygoteState不为null
- if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
- try {
- //看过Zygote启动的知道,Zygote存在主辅模式
- //比如我设备是以Zygote64位主(secondary),Zygote32位辅(secondary)模式
- //连接socket,这个是Zygote中创建的,
- primaryZygoteState = ZygoteState.connect(mSocket);
- } catch (IOException ioe) {
- throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
- }
- maybeSetApiBlacklistExemptions(primaryZygoteState, false);
- maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
- }
- //具体使用哪种模式,跟abi有关
- if (primaryZygoteState.matches(abi)) {
- return primaryZygoteState;
- }
- //下面类型,但如果上面符合,就不会执行下面了。
- if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
- try {
- secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
- } catch (IOException ioe) {
- throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
- }
- maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
- maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
- }
- if (secondaryZygoteState.matches(abi)) {
- return secondaryZygoteState;
- }
- throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
- }
回归一下之前介绍的,不同设备使用的配置不一样。
下面是几个zygote相关的rc文件。
init.zygote32.rc
Zygote 进程对应的执行程序是 app_process,也就是纯32位模式。
init.zygote32_64.rc
启动两个 Zygote 进程(zygote 和 zygote_secondary),对应的执行程序分别是 app_process32(主模式)和app_process64。
init.zygote64.rc
Zygote 进程对应的执行程序是app_process64,也就是纯64位模式
init.zygote64_32.rc
启动两个 Zygote 进程(zygote 和 zygote_secondary),对应的执行程序分别是 app_process64(主模式)和app_process32。
会根据primaryZygoteState和secondaryZygoteState的初始化,进程判断,如果都不满足(启动失败了或重启中),就抛出异常!
理论上,至少有一个满足条件。
因此,经过上面执行,已建成跟Zygote进行通信了,并返回ZygoteState。
zygoteSendArgsAndGetResult()
- @GuardedBy("mLock")
- private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
- ZygoteState zygoteState, ArrayList<String> args)
- throws ZygoteStartFailedEx {
- try {
- //略
- //ZygoteState就是上面openZygoteSocketIfNeeded()获取的
- //获取writer和inputStream
- final BufferedWriter writer = zygoteState.writer;
- final DataInputStream inputStream = zygoteState.inputStream;
- //写启动上面组合的启动参数信息
- //此时就进入ZygoteServer.java中runSelectLoop()的死循环中啦
- 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();
- //创建ProcessStartResult对象
- Process.ProcessStartResult result = new Process.ProcessStartResult();
- //等待,zygote启动进程结构
- 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);
- }
- }
上面就是通过socket进程传输启动应用的新,因此,进入了ZygoteServer.java中runSelectLoop()中。
对于Zygote的socket的那块,推荐可以看参考文,之前我有跟过。
ZygoteServer.java
通过socket发送消息,runSelectLoop()会一直不断的循环并进行处理。
runSelectLoop()
- Runnable runSelectLoop(String abiList) {
- //这部分第一次进入才执行,后面的进入了死循环了。
- //死循环
- while (true) {
- //略
- for (int i = pollFds.length - 1; i >= 0; --i) {
- //采用I/O多路复用机制,当客户端发出连接请求或者数据处理请求时,则执行continue
- if ((pollFds[i].revents & POLLIN) == 0) {
- continue;
- }
- if (i == 0) {
- //有socket客户端连接上
- ZygoteConnection newPeer = acceptCommandPeer(abiList);
- peers.add(newPeer);
- fds.add(newPeer.getFileDesciptor());
- } else {
- try {
- //客户端发送了请求,获取connection
- ZygoteConnection connection = peers.get(i);
- //[重]处理发送来的消息,其实这里就处理fork出子进程
- //切记,返回的是Runnable,这里进入
- final Runnable command = connection.processOneCommand(this);
- //这里要对fork有一定了解,创建子进程就是Zygote的分裂
- //下面的if语句都会执行
- //一个是走父进程流程关闭socket;一个是子进程流程,启动进程ActivityThread
- if (mIsForkChild) {
- //如果在子进程,command不为null
- if (command == null) {
- throw new IllegalStateException("command == null");
- }
- return command;
- } else {
- //父进程,command为null
- if (command != null) {
- throw new IllegalStateException("command != null");
- }
- //关闭socket等
- if (connection.isClosedByPeer()) {
- connection.closeSocket();
- peers.remove(i);
- fds.remove(i);
- }
- }
- } catch (Exception e) {
- //略
- } finally {
- mIsForkChild = false;
- }
- }
- }
- }
- }
从socket中接收消息,然后进程fork出子进程(也就是从zygote中分裂而来)。
然后主进程流程关闭socket,子进程流程启动ActivityThread。
我们先挂住processOneCommand()这块。
ZygoteConnection.java
processOneCommand()
- Runnable processOneCommand(ZygoteServer zygoteServer) {
- String args[];
- Arguments parsedArgs = null;
- FileDescriptor[] descriptors;
- try {
- //从socket读取命令
- args = readArgumentList();
- descriptors = mSocket.getAncillaryFileDescriptors();
- } catch (IOException ex) {
- throw new IllegalStateException("IOException on command socket", ex);
- }
- //如果没有参数,直接结束
- if (args == null) {
- isEof = true;
- return null;
- }
- int pid = -1;
- FileDescriptor childPipeFd = null;
- FileDescriptor serverPipeFd = null;
- //创建Arguments对象,这里会解析args中的命令
- parsedArgs = new Arguments(args);
- //根据参数值进行处理
- if (parsedArgs.abiListQuery) {
- handleAbiListQuery();
- return null;
- }
- //略
- //fork出子进程
- pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
- parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
- parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
- parsedArgs.instructionSet, parsedArgs.appDataDir);
- try {
- if (pid == 0) {
- //子进程流程
- zygoteServer.setForkChild();
- zygoteServer.closeServerSocket();
- IoUtils.closeQuietly(serverPipeFd);
- serverPipeFd = null;
- //[重]返回Runnable
- return handleChildProc(parsedArgs, descriptors, childPipeFd,
- parsedArgs.startChildZygote);
- } else {
- IoUtils.closeQuietly(childPipeFd);
- childPipeFd = null;
- //如果是父进程流程
- handleParentProc(pid, descriptors, serverPipeFd);
- return null;
- }
- } finally {
- IoUtils.closeQuietly(childPipeFd);
- IoUtils.closeQuietly(serverPipeFd);
- }
- }
handleChildProc()
- private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
- FileDescriptor pipeFd, boolean isZygote) {
- //关闭socket
- closeSocket();
- //根据之前传入参数,invokeWith=null
- if (parsedArgs.invokeWith != null) {
- WrapperInit.execApplication(parsedArgs.invokeWith,
- parsedArgs.niceName, parsedArgs.targetSdkVersion,
- VMRuntime.getCurrentInstructionSet(),
- pipeFd, parsedArgs.remainingArgs);
- throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
- } else {
- //走这里
- //isZygote为false,是依赖parsedArgs.startChildZygote
- if (!isZygote) {
- return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
- null /* classLoader */);
- } else {
- return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
- parsedArgs.remainingArgs, null /* classLoader */);
- }
- }
- }
ZygoteInit.java
zygoteInit()
- public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
- //这参数是ActivityManagerService.java中startProcessLocked()中[上面倒数第二个]传入的
- //argv中带有android.app.ActivityThread参数。
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
- RuntimeInit.redirectLogStreams();
- RuntimeInit.commonInit();
- ZygoteInit.nativeZygoteInit();
- return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
- }
RuntimeInit.java
applicationInit()
- protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
- ClassLoader classLoader) {
- nativeSetExitWithoutCleanup(true);
- VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
- VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
- final Arguments args = new Arguments(argv);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- //[重]看方法名就知道,找到main方法入口
- //args.startClass = android.app.ActivityThread
- return findStaticMain(args.startClass, args.startArgs, classLoader);
- }
findStaticMain()
- protected static Runnable findStaticMain(String className, String[] argv,
- ClassLoader classLoader) {
- Class<?> cl;
- //是不是很熟悉,反射
- try {
- cl = Class.forName(className, true, classLoader);
- } catch (ClassNotFoundException ex) {
- throw new RuntimeException(
- "Missing class when invoking static main " + className,
- ex);
- }
- Method m;
- try {
- //查找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);
- }
- //创建MethodAndArgsCaller,MethodAndArgsCaller实现于Runnable
- return new MethodAndArgsCaller(m, argv);
- }
MethodAndArgsCaller
- static class MethodAndArgsCaller implements Runnable {
- private final Method mMethod;
- private final String[] mArgs;
- public MethodAndArgsCaller(Method method, String[] args) {
- mMethod = method;
- mArgs = args;
- }
- public void run() {
- try {
- //Method = com.android.server.SystemServer的main函数
- //这里会启动ActivityThread并执行main()方法
- mMethod.invoke(null, new Object[] { mArgs });
- } catch (IllegalAccessException ex) {
- //略
- }
- }
- }
到这里,Runnable已经创建了,但之前仅仅是创建了Runnable,但没有执行run(),因此我们要回到runSelectLoop()中。
ZygoteServer.java
再次回答runSelectLoop()中,里面有这段代码[只是部分]
- try {
- //客户端发送了请求,获取connection
- ZygoteConnection connection = peers.get(i);
- //[重]处理发送来的消息,其实这里就处理fork出子进程
- //切记,返回的是Runnable,这里进入
- final Runnable command = connection.processOneCommand(this);
- //这里要对fork有一定了解,创建子进程就是Zygote的分裂
- //下面的if语句都会执行
- //一个是走父进程流程关闭socket;一个是子进程流程,启动进程ActivityThread
- if (mIsForkChild) {
- //如果在子进程,command不为null
- if (command == null) {
- throw new IllegalStateException("command == null");
- }
- return command;
- } else {
- //父进程,command为null
- if (command != null) {
- throw new IllegalStateException("command != null");
- }
- //关闭socket等
- if (connection.isClosedByPeer()) {
- connection.closeSocket();
- peers.remove(i);
- fds.remove(i);
- }
- }
- } catch (Exception e) {
- //略
- } finally {
- mIsForkChild = false;
- }
上面也说了fork后,会有两个执行流程,一个是父进程流程,一个是子进程流程。我们关注子进程流程。
也就是mIsForkChild为true时,此时command不为null,而是
- command = new MethodAndArgsCaller(m, argv);
也就是runSelectLoop()执行结束,并返回Runnable。
fork是把父类所有的资源都拷贝一份给子进程,因此,上面退出的runSelectLoop()循环是子类的。
子类用户父类Zygote一样的代码流程。ZygoteInit.java是进入Java世界的第一扇大门!
runSelectLoop()也是在ZygoteInit.java中main()方法中的。
ZygoteInit.java
- public static void main(String argv[]) {
- //创建ZygoteServer
- ZygoteServer zygoteServer = new ZygoteServer();
- final Runnable caller;
- try {
- //略
- //[重]循环中。对于zygote不会退出,至于fork的子进程,是会退出的
- caller = zygoteServer.runSelectLoop(abiList);
- } catch (Throwable ex) {
- throw ex;
- } finally {
- //关闭socket
- zygoteServer.closeServerSocket();
- }
- //子进程退出的caller不为null
- if (caller != null) {
- caller.run();
- }
- }
fork出的子进程才会退出runSelectLoop()循环,因此上面的call就是返回的Runnable对象,也就是这里main()方法结束后执行了
- MethodAndArgsCaller.run();
然后进入了ActivityThread.java的main(),至于后面的,可以看《
参考文章
《》
《》
《》
《》