Android 7.0应用启动流程分析
<p>最近在为自己Moto G定制Rom,顺便重新读了一遍Android 7.0的相关源码,特此记录当做笔记.</p> <p>在开始正文之前,首先要明白冷启动和热启动.所谓冷启动就是启动该应用时,后台没有该应用的进程,此时系统会创建一个进程分配给它(AMS通过Socket和Zygote通信,Zygote通过forkAndSpecialize()方法向Linux内核申请新进程),之后会创建和初始化Application,然后通过反射执行ActivityThread中的main方法.而热启动则是,当启动应用的时候,后台已经存在该应用的进程,比如按home键返回主界面再打开该应用,此时会从已有的进程中来启动应用,这种方式下,不会重新走Application这一步.</p> <p>那今天我们主要分析的是应用冷启动的过程.在分析过程中,我发现从Android 2.3到Android 7.0的启动流程总体变化不大,所以,无论你目前是用何版本,下文多是通用的.另外,在本文中,我省略掉了有关Binder这一部分,以便大部分人都能顺利阅读.</p> <h2>从Launcher点击开始</h2> <p>Launcher就是我们所说的桌面,它本质也是一个apk,当我们点击桌面上的图标时,会调用Activity的 startActivity() ,最终调用 startActivityForResult() :</p> <pre> <code class="language-java">public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); // 省略多行代码 } else { // 省略多行代码 } }</code></pre> <p>startActivityForResult将创建过程委托给Instrumenttation的 execStartActivity() :</p> <pre> <code class="language-java">public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { //重点关注IApplicationThread IApplicationThread whoThread = (IApplicationThread) contextThread; Uri referrer = target != null ? target.onProvideReferrer() : null; if (referrer != null) { intent.putExtra(Intent.EXTRA_REFERRER, referrer); } if (mActivityMonitors != null) { synchronized (mSync) { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; } break; } } } } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(); // 重点关注ActivityManagerNative int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; }</code></pre> <p>在该方法签名中,我们看到第二个参数contextThread是IBinder类型,继续往下看,发现contextThread实则是IApplicationThread的实现类.简单来看IApplicationThread的定义:</p> <pre> <code class="language-java">public interface IApplicationThread extends IInterface { void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException; void scheduleStopActivity(IBinder token, boolean showWindow, int configChanges) throws RemoteException; void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException; void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException; void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs) throws RemoteException; void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException; void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException; void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed, Configuration config, Configuration overrideConfig) throws RemoteException; void scheduleNewIntent(List<ReferrerIntent> intent, IBinder token) throws RemoteException; void scheduleDestroyActivity(IBinder token, boolean finished, int configChanges) throws RemoteException; void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, boolean sync, int sendingUser, int processState) throws RemoteException; // 省略多个方法 void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) throws RemoteException; void scheduleUnbindService(IBinder token, Intent intent) throws RemoteException; //省略多个方法 void scheduleStopService(IBinder token) throws RemoteException; //省略多个方法 void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers, ComponentName testName, ProfilerInfo profilerInfo, Bundle testArguments, IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection, int debugMode, boolean openGlTrace, boolean restrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) throws RemoteException; void scheduleExit() throws RemoteException; // 省略多行代码 void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser, int processState) throws RemoteException; void scheduleLowMemory() throws RemoteException; void scheduleActivityConfigurationChanged(IBinder token, Configuration overrideConfig) throws RemoteException; //省略多个方法 void scheduleTrimMemory(int level) throws RemoteException; //省略多个方法 }</code></pre> <p>通过大体的阅读IApplicationThread中代码,我们隐约有些熟悉,比如 schedulePauseActivity 方法应该就是负责Activity中 Pause() 执行的, scheduleLaunchActivity() 应该是负责Activity创建的, scheduleBindService() 负责Service绑定的,到现在,我们心里应该会想到IApplicationThread的真正实现类ApplicationThread(位于ActivityThread.java中)就是负责Activity,Service等的创建或其他操作,先来简单的看起其类关系图:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/853a01677a75763b1e185a7f68afc2da.png"></p> <p>我们继续看Instrumentation的 execStartActivity() 方法:</p> <pre> <code class="language-java">int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);</code></pre> <p>此时启动Activity这一操作交给了ActivityManagerNative.getDefault()的startActivity()方法.ActivityManagerNative是一个抽象类,继承了Binder,同时它又实现了IActivityManager接口,其实现类是ActivityManagerService(AMS).</p> <p>ActivityManagerNative.getDefault()方法返回IActivityManager类型对象,其实现类是ActivityManagerProxy,其构造函数接受一个IBinder类型,其实就是ActivityManagerService对象,此时你应该发现ActivityManagerNative,IActivityManager以及ActivityManagerProxy三者之间的联系如下:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/8dfbce384da65fefd99803320bf887d8.png"></p> <p>通过上图,我们看到这三者就是一个典型的代理模式:ActivityManagerProxy就是ActivityManagerService的远程代理,那么此时ActivityManagerNative的作用也就很明显:返回AMS的远程代理对象,这样Launcher应用就能和AMS服务通信了.</p> <p>我们用一张图来简单的描述上述整个流程:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/a0ede84bb438c409de315d38307b3e5e.png"></p> <h2>进入ActivityManagerService</h2> <p>现在我们跳到AMS的 startActivity() 方法继续往下看:</p> <pre> <code class="language-java">@Override public int startActivity(IBinder whoThread, String callingPackage, Intent intent, String resolvedType, Bundle options) { checkCaller(); int callingUser = UserHandle.getCallingUserId(); TaskRecord tr; IApplicationThread appThread; synchronized (ActivityManagerService.this) { tr = mStackSupervisor.anyTaskForIdLocked(mTaskId); if (tr == null) { throw new IllegalArgumentException("Unable to find task ID " + mTaskId); } appThread = ApplicationThreadNative.asInterface(whoThread); if (appThread == null) { throw new IllegalArgumentException("Bad app thread " + appThread); } } //交给mStackSupervisor继续 return mStackSupervisor.startActivityMayWait(appThread, -1, callingPackage, intent, resolvedType, null, null, null, null, 0, 0, null, null, null, options, false, callingUser, null, tr); }</code></pre> <p>首先我们注意到该方法的第一个参数是IBinder类型,其实质就是前边ApplicationThread的实例,也就是ActivityThread中的mAppThread对象.接下来交给ActivityStackSupervisor实例的 startActivityMayWait() 继续启动:</p> <pre> <code class="language-java">final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, WaitResult outResult, Configuration config, Bundle options, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, TaskRecord inTask) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); } boolean componentSpecified = intent.getComponent() != null; // Don't modify the client's object! intent = new Intent(intent); // Collect information about the target of the Intent. ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId); ActivityContainer container = (ActivityContainer)iContainer; synchronized (mService) { //省略多行代码 int res = startActivityLocked(caller, intent, resolvedType, aInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, null, container, inTask); // 省略多行代码 return res; } }</code></pre> <p>该方法看起来非常复杂,但是流程确实蛮清晰的,通过 resolveActivity() 方法来获取ActivityInfo,接下来是一些其他操作(在不影响流程的前提下,省略多行),然后继续调用 startActivityLocked() :</p> <pre> <code class="language-java">final int startActivityLocked(IApplicationThread caller, Intent intent, String resolvedType, ActivityInfo aInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, Bundle options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container, TaskRecord inTask) { int err = ActivityManager.START_SUCCESS; //省略多行代码 err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask); return err; }</code></pre> <p>在该方法中,又继续调用了 startActivityUncheckedLocked() 方法,抛开其中细节,我们发现该方法中又继续调用了ActivityStack的 resumeTopActivityLocked() 来继续启动流程:</p> <pre> <code class="language-java">final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) { if (mStackSupervisor.inResumeTopActivity) { // Don't even start recursing. return false; } boolean result = false; try { // Protect against recursion. mStackSupervisor.inResumeTopActivity = true; if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) { mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN; mService.updateSleepIfNeededLocked(); } //继续启动 result = resumeTopActivityInnerLocked(prev, options); } finally { mStackSupervisor.inResumeTopActivity = false; } return result; }</code></pre> <p>从上面的代码看出, resumeTopActivitiesLocked() 方法继续调用了 resumeTopActivityInnerLocked() 方法,该方法内部又反过来调用了ActivityStackSupervisor的 resumeTopActivitiesLocked() 方法</p> <pre> <code class="language-java">private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) { //省略多行代码 mStackSupervisor.startSpecificActivityLocked(next, true, false); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; }</code></pre> <p>在上述代码中,由于应用是第一次启动,因此这里跳过了一些判断代码,最终又调用了ActivityStackSupervisor的 startSpecificActivityLocked() 来继续启动流程:</p> <pre> <code class="language-java">void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // Is this activity's application already running? ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); r.task.stack.setLaunchTime(r); //该应用的进程已经存在 if (app != null && app.thread != null) { try { if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) { app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats); } realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e); } } //该应用的进程尚未创建,调用AMS的startProcessLocked() mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }</code></pre> <p>应用是第一次启动,此时系统尚未为其创建进程,因此调用AMS的 startProcessLocked() 方法,如果该应用已经存在,则调用 realStartActivityLocked() .由于这里我们的应用第一次启动,所以从 startProcessLocked() 往下看:</p> <pre> <code class="language-java">final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, boolean keepIfLarge) { return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,hostingName, allowWhileBooting, isolated, 0 , keepIfLarge,null , null , null,null); }</code></pre> <p>该方法直接调用了其对应的重载方法,并在该其中继续调用了重载方法:</p> <pre> <code class="language-java">private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { long startTime = SystemClock.elapsedRealtime(); //省略多行代码 boolean isActivityProcess = (entryPoint == null); //默认情况下,entryPoint为null,此时虚拟机启动后默认从ActivityThread的main()方法执行 if (entryPoint == null) entryPoint = "android.app.ActivityThread"; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " + app.processName); //要求Zygote进程为其创建进程 checkTime(startTime, "startProcess: asking zygote to start proc"); 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); //省略多行代码 } catch (RuntimeException e) { //省略 } }</code></pre> <p>到现在我们同样用一张图来描述这过程:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/2374470a84c41929f6b240d43b74e9f2.png"></p> <h2>走进Zygote</h2> <p>这里通过Process的 start() 方法来请求Zygote进程为其生成新进程,在 start() 方法中又直接调用了 startViaZygote() :</p> <pre> <code class="language-java">//processClass是调用者传的android.app.ActivityThread 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<String> argsForZygote = new ArrayList<String>(); // --runtime-args, --setuid=, --setgid=, // and --setgroups= must go first //--runtime-agrs决定了新建进程执行方式, 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_DEBUGGER) != 0) { argsForZygote.add("--enable-debugger"); } if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) { argsForZygote.add("--enable-checkjni"); } if ((debugFlags & Zygote.DEBUG_ENABLE_JIT) != 0) { argsForZygote.add("--enable-jit"); } if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) { argsForZygote.add("--generate-debug-info"); } 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); //TODO optionally enable debuger //argsForZygote.add("--enable-debugger"); // --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); } argsForZygote.add(processClass); if (extraArgs != null) { for (String arg : extraArgs) { argsForZygote.add(arg); } } return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } }</code></pre> <p>上面的方法非常简单,设置一堆参数后然后又调用了 zygoteSendArgsAndGetResult() 向Zygote发送创建进程请求,该方法内部就是和Zygote进行Socket通信.Zygote接受到该请求,并将该请求封装为ZygoteConnection对象,具体代码在ZygoteInit.java当中,来看 runSelectLoop() :</p> <pre> <code class="language-java">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 { 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) { //接受来自AMS的请求 ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { boolean done = peers.get(i).runOnce(); if (done) { peers.remove(i); fds.remove(i); } } } } }</code></pre> <p>此时Zygote作为服务端不断监听来自AMS的请求,通过 acceptCommandPeer() 将请求封装为ZygoteConection对象,并将Socket文件标识存在fds中,请求放在peers中.而 runOnce() 则在下一次循环中处理请求,具体代码如下:</p> <pre> <code class="language-java">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; } //省略多行代码 /** the stderr of the most recent request, if avail */ PrintStream newStderr = null; if (descriptors != null && descriptors.length >= 3) { newStderr = new PrintStream( new FileOutputStream(descriptors[2])); } int pid = -1; FileDescriptor childPipeFd = null; FileDescriptor serverPipeFd = null; try { //将请求参数封装成Arguments对象 parsedArgs = new Arguments(args); //省略多行代码 //创建新进程或者说创建VM实例 pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,parsedArgs.appDataDir); } catch (ErrnoException ex) { //省略多行代码 } try { if (pid == 0) {//pid=0表示刚才fork出的子进程 IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; 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 IoUtils.closeQuietly(childPipeFd); childPipeFd = null; return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } }</code></pre> <p>上面的代码比较简单主要是读取请求参数并将其封装为Arguments对象,Arguments包含一下参数:</p> <pre> <code class="language-java">--setuid= --setgid= --target-sdk-version= --enable-debugger --enable-safemode --enable-checkjni --enable-jit --generate-debug-info --enable-jni-logging --enable-assert --runtime-args --seinfo= --capabilities= --rlimit= --setgroups= --invoke-with --nice-name= --mount-external-default --mount-external-read --mount-external-write --query-abi-list --instruction-set= --app-data-dir=</code></pre> <p>并通过Zygote的 forkAndSpecialize() 来生成新进程,成功后pid的值为0,这里我们只关心创建成功的情况,接下来,在新的进程中关闭从Zygote继承来的Socket,然后通过 handleChildProc() 继续后续操作.</p> <pre> <code class="language-java">private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { //关闭AMS和Zygote之间的Socket连接 closeSocket(); ZygoteInit.closeServerSocket(); if (descriptors != null) { try { Os.dup2(descriptors[0], STDIN_FILENO); Os.dup2(descriptors[1], STDOUT_FILENO); Os.dup2(descriptors[2], STDERR_FILENO); for (FileDescriptor fd: descriptors) { IoUtils.closeQuietly(fd); } newStderr = System.err; } catch (ErrnoException ex) { Log.e(TAG, "Error reopening stdio", ex); } } if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); } // End of the postFork event. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); if (parsedArgs.invokeWith != null) { //通过系统调用执行进程 WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, VMRuntime.getCurrentInstructionSet(), pipeFd, parsedArgs.remainingArgs); } else { //寻找相应目标类的main()方法并执行 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */); } }</code></pre> <p>这里根据invokeWith参数决定使用哪种执行方式,invokeWith不为空则通过WrapperInit执行,否则通过RuntimeInit方式执行.对于这两者不做过多的解释,参数—runtime-args决定了新进程都是以RuntimeInit方式启动,目前就记住SystemServer和apk都是通过RuntimeInit来的即可.</p> <h2>走进RuntimeInit</h2> <p>现在来看RuntimeInit的 zygoteInit() 方法:</p> <pre> <code class="language-java">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"); redirectLogStreams(); commonInit(); nativeZygoteInit(); applicationInit(targetSdkVersion, argv, classLoader); }</code></pre> <p>commonInit() 为VM设置默认了线程异常处理器,然后调用了本地方法 nativeZygoteInit() ,其具体实现在AndroidRuntime.cpp下,位于frameworks/base/core/jni/AndroidRuntime.cpp</p> <pre> <code class="language-java">static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz) { gCurRuntime->onZygoteInit(); }</code></pre> <p>在该方法中又调用了其子类AppRutime的 onZygoteInit() 方法,AppRuntime位于frameworks/base/cmds/app_process/app_main.cpp</p> <pre> <code class="language-java">virtual void onZygoteInit() { sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); }</code></pre> <p>为了不影响后文,我们先回到RuntimeInit的 applicationInit() :</p> <pre> <code class="language-java">private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { nativeSetExitWithoutCleanup(true); //VM设置 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; } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); //反射执行ActivityThread的main函数 invokeStaticMain(args.startClass, args.startArgs, classLoader); }</code></pre> <p>其中最关键的就是 invokeStaticMain() 方法:</p> <pre> <code class="language-java">private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { 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 { 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); } //该异常会在ZygoteInit.main()中被捕获,然后在异常处理中调用MethodAndArgsCaller的run() //方法,这样就清除了进程中所有的栈帧 throw new ZygoteInit.MethodAndArgsCaller(m, argv); }</code></pre> <p>在上面的代码中,最终的执行是通过抛出MethodAndArgsCaller的方式,来看一下MethodAndArgsCaller类的定义:</p> <pre> <code class="language-java">public static class MethodAndArgsCaller extends Exception 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 }); } 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); } } }</code></pre> <p>MethodAndArgsCaller继承Exception类并实现Runnable接口.但不管如何,现在最终开始执行ActivityThread的入口函数main():</p> <pre> <code class="language-java">public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start(); CloseGuard.setEnabled(false); Environment.initForCurrentUser(); EventLogger.setReporter(new EventLoggingReporter()); AndroidKeyStoreProvider.install(); final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }</code></pre> <p>当main()开始运行时,主线程正式开始运行,这也就是我们所说的UI线程.同样我们用一张简单的图来描述上述过程:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/e4f59d78b7847f93042a18d22609aad6.png"></p> <h2>总结</h2> <p>到现在,我们已经完全走完应用冷启动的流程,上面的过程看起来繁琐,但是结合时序图来看应该是比较清晰的.抛开细节不看,那么上述的整个流程可以用下图概括:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/b21b2e71809b3412d120c45c662921c8.png"></p> <p>最后为了方便系统理解整个流程,附上一张相对完整的时序图:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/2447577fe59278e84b8b3b3fbedd3fdd.jpg"></p> <p> </p> <p>来自:http://blog.csdn.net/dd864140130/article/details/60466394</p> <p> </p>
本文由用户 DemiHung 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
转载本站原创文章,请注明出处,并保留原始链接、图片水印。
本站是一个以用户分享为主的开源技术平台,欢迎各类分享!