目录

一、应用内启动

1.先简单的看一下调用关系时序图(基于android28源码)

2.源码分析

Activity.java

Instrumentation.java

ActivityManagerService.java

ActivityStarter.java

ActivityStackSupervisor.java

ActivityStack.java

ActivityThread.java

二、Launcher图标启动

1.流程总结

2.时序图

3.源码分析

Launcher.java

先来看看怎么调到Zygote进程去fork app进程的。ActivityManagerService.java

Process.java

ZygoteProcess.java

接下来是从ActivityThread的main方法如何绑定applicationThread,再如何启动activity的。ActivityThread.java

三、流程总结


一、应用内启动

我们平时启动一个activity一般都是调用startActivity方法,接下来就看看startActivity方法具体为我们执行了哪些流程去帮我们启动一个activity吧。

1.先简单的看一下调用关系时序图(基于android28源码)

我知道你可能看不清,点击链接查看时序图

2.源码分析

  • Activity.java

    @Overridepublic void startActivity(Intent intent) {this.startActivity(intent, null);}@Overridepublic void startActivity(Intent intent, @Nullable Bundle options) {if (options != null) {startActivityForResult(intent, -1, options);} else {// Note we want to go through this call for compatibility with// applications that may have overridden the method.startActivityForResult(intent, -1);}}//从这里可以看出startActivity最终都会调用startActivityForResult方法public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {if (mParent == null) {...//调用Instrumentation的execStartActivity方法Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);...}}...}
  • Instrumentation.java

public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {//获得ApplicationThreadIApplicationThread whoThread = (IApplicationThread) contextThread;...//省略部分代码try {intent.migrateExtraStreamToClipData();intent.prepareToLeaveProcess(who);//获得AMS的客户端,通过Binder调用AMS服务中的startActivity方法,//将ApplicationThread也传给AMS方便后续交换信息int result = ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);//这里检查activity启动返回值checkStartActivityResult(result, intent);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null;}//检查startActivity的返回值抛出异常信息,例如没有在清单配置文件中注册
public static void checkStartActivityResult(int res, Object intent) {if (!ActivityManager.isStartResultFatalError(res)) {return;}switch (res) {case ActivityManager.START_INTENT_NOT_RESOLVED:case ActivityManager.START_CLASS_NOT_FOUND:if (intent instanceof Intent && ((Intent)intent).getComponent() != null)throw new ActivityNotFoundException("Unable to find explicit activity class "+ ((Intent)intent).getComponent().toShortString()+ "; have you declared this activity in your AndroidManifest.xml?");throw new ActivityNotFoundException("No Activity found to handle " + intent);...//省略部分代码}}
  • ActivityManagerService.java

    @Overridepublic final int startActivity(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {//增加userId参数,不做处理调用startActivityAsUser方法return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,resultWho, requestCode, startFlags, profilerInfo, bOptions,UserHandle.getCallingUserId());}public final int startActivityAsUser(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,boolean validateIncomingUser) {enforceNotIsolatedCaller("startActivity");userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");// TODO: Switch to user app stacks here.return mActivityStartController.obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(bOptions).setMayWait(userId)//设置mayWait属性为true.execute();}
  • ActivityStarter.java

    int execute() {try {// TODO(b/64750076): Look into passing request directly to these methods to allow// 从上面的代码我们知道mayWait为trueif (mRequest.mayWait) {//执行startActivityMayWait方法return startActivityMayWait(mRequest.caller, mRequest.callingUid,mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,mRequest.inTask, mRequest.reason,mRequest.allowPendingRemoteAnimationRegistryLookup);} else {...//省略部分代码}} finally {onExecutionComplete();}}private 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 globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,int userId, TaskRecord inTask, String reason,boolean allowPendingRemoteAnimationRegistryLookup) {//...省略部分代码// 收集target的信息ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);//继续执行startActivityint res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,allowPendingRemoteAnimationRegistryLookup);//...return res;}}private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,String callingPackage, int realCallingPid, int realCallingUid, int startFlags,SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,ActivityRecord[] outActivity, TaskRecord inTask, String reason,boolean allowPendingRemoteAnimationRegistryLookup) {//...//继续调用startActivitymLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,inTask, allowPendingRemoteAnimationRegistryLookup);//...return getExternalResult(mLastStartActivityResult);}private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,String callingPackage, int realCallingPid, int realCallingUid, int startFlags,SafeActivityOptions options,boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {//err默认为Successint err = ActivityManager.START_SUCCESS;//...//开始根据之前收集到的信息判断返回值是否有误,如果启动失败,返回err信息,还记得我们之前在Instrumentation里的启动信息检查吗?if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {// We couldn't find a class that can handle the given Intent.// That's the end of that!err = ActivityManager.START_INTENT_NOT_RESOLVED;//这个错误信息还有印象吗?}if (err == ActivityManager.START_SUCCESS && aInfo == null) {// We couldn't find the specific class specified in the Intent.// Also the end of the line.err = ActivityManager.START_CLASS_NOT_FOUND;//这里是不是很熟悉?}//如果启动不成功返回errif (err != START_SUCCESS) {if (resultRecord != null) {resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);}SafeActivityOptions.abort(options);return err;}//...//检查过没有错误的话,继续调用startActivityreturn startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,true /* doResume */, checkedOptions, inTask, outActivity);}private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,ActivityRecord[] outActivity) {int result = START_CANCELED;try {mService.mWindowManager.deferSurfaceLayout();//继续调用startActivityUncheckedresult = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, outActivity);} finally {//...}//...return result;}private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,ActivityRecord[] outActivity) {//...省略代码,一系列的活动栈操作,判断FLAG_ACTIVITY_NEW_TASK、FLAG_ACTIVITY_CLEAR_TOP等if (mDoResume) {final ActivityRecord topTaskActivity =mStartActivity.getTask().topRunningActivityLocked();if (!mTargetStack.isFocusable()|| (topTaskActivity != null && topTaskActivity.mTaskOverlay&& mStartActivity != topTaskActivity)) {//...} else {//...//能够获取焦点的activity启动走这里mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,mOptions);}} //...return START_SUCCESS;}
  • ActivityStackSupervisor.java

    boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {//...//继续调用ActivityStack的resumeTopActivityUncheckedLockedreturn targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);//...return false;}void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {//...//如果应用已经启动执行这里if (app != null && app.thread != null) {try {//...//继续调用realStartActivityLocked方法realStartActivityLocked(r, app, andResume, checkConfig);return;} catch (RemoteException e) {Slog.w(TAG, "Exception when starting activity "+ r.intent.getComponent().flattenToShortString(), e);}}//如果第一次启动应用执行这里,先去Zygote进程fork出一个新的进程mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);}final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,boolean andResume, boolean checkConfig) throws RemoteException {//...// 创建activity启动事物final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,r.appToken);//设置回调,最终是由LaunchActivityItem调用的我们最熟悉的handleLaunch方法clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,// TODO: Have this take the merged configuration instead of separate global// and override configs.mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,r.persistentState, results, newIntents, mService.isNextTransitionForward(),profilerInfo));//执行事物,这里会调用ClientTransaction的schedule方法//然后调用到ApplicationThread的scheduleTransaction方法//最终调用到ActivityLifecycleItem的execute方法mService.getLifecycleManager().scheduleTransaction(clientTransaction);//...return true;}
  • ActivityStack.java

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {if (mStackSupervisor.inResumeTopActivity) {// Don't even start recursing.return false;}boolean result = false;try {// Protect against recursion.mStackSupervisor.inResumeTopActivity = true;//继续调用resumeTopActivityInnerLocked方法result = resumeTopActivityInnerLocked(prev, options);//...} finally {mStackSupervisor.inResumeTopActivity = false;}return result;}private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {//...//暂停上一个activityboolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);//...//这里相当于上一个页面是透明的,且要启动的activity已经存在的时候,尝试直接启动if (next.app != null && next.app.thread != null) {//...} else {//...//第一次启动activity走这里,又回到了ActivityStackSupervisor类里mStackSupervisor.startSpecificActivityLocked(next, true, true);}return true;}
  • ActivityThread.java

    public Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {//...//熟悉的地方,再后面就是用Instrumentation类newActivity,绑定application,//调用callActivityOnCreate方法最终调用到activity的onCreate方法了,我就不写了。final Activity a = performLaunchActivity(r, customIntent);//...return a;}

二、Launcher图标启动

1.流程总结

图标启动的话,其实是从Launcher类点击应用图标之后也使用startActivity启动指定的activity,而Launcher也是一个Activity。

当然这里启动流程与应用内启动有些不同,还记得我们上面在ActivityStackSupervisor.java中的startSpecificActivityLocked方法中判断如果应用进程未启动需要先调用Zygote进程fork一个新的app进程吗?

之后又是我们熟悉的ActivityThread的main方法,与AMS利用Binder通信绑定application,完成后查看查看顶部可见的activity是否在此进程中等待运行,是的话执行ActivityStackSupervisor.java中的realStartActivityLocked方法,后面的流程又和应用内启动一样了。

2.时序图

这个时序图包括了,AMS如果调用到Zygote进程去fork app的,然后ActivityThread是如何再到ActivityStackSupervisor去启动activity的,以及附加了application是在哪创建的以及application的onCreate和providers的install顺序。

看不清请点击链接查看

3.源码分析

  • Launcher.java

注意这个类在/packages/apps/Launcher2/src/com/android/launcher2下,源码链接

ok看着到这里,我们知道图标启动也是startActivity了,但是这时候如果我们第一次启动app,明显app进程还没有创建,所以接下里我们分析下怎么创建的app进程,然后又是如何启动的首页。

  • 先来看看怎么调到Zygote进程去fork app进程的。ActivityManagerService.java

    //以下是启动新app进程相关代码final ProcessRecord startProcessLocked(String processName,ApplicationInfo info, boolean knownToBeDead, int intentFlags,String hostingType, ComponentName hostingName, boolean allowWhileBooting,boolean isolated, boolean keepIfLarge) {//继续调用startProcessLockedreturn 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) {//...//继续调用startProcessLocked方法final boolean success = startProcessLocked(app, hostingType, hostingNameStr, abiOverride);//...return success ? app : null;}private final boolean startProcessLocked(ProcessRecord app,String hostingType, String hostingNameStr, String abiOverride) {//还在继续调startProcessLockedreturn startProcessLocked(app, hostingType, hostingNameStr,false /* disableHiddenApiChecks */, abiOverride);}private final boolean startProcessLocked(ProcessRecord app, String hostingType,String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {//...try {//...//继续调用return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,startTime);} catch (RuntimeException e) {//...}}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) {//...//这两个分支我也不知道是走同步还是异步,但是最后他们都是调用的startProcess方法if (mConstants.FLAG_PROCESS_START_ASYNC) {//...mProcStartHandler.post(() -> {try {//...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) {//...}});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) {//...}return app.pid > 0;}}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 {//...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.startstartResult = 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);}}//以下是绑定application相关代码,从ActivityThread调用的public final void attachApplication(IApplicationThread thread, long startSeq) {synchronized (this) {int callingPid = Binder.getCallingPid();final int callingUid = Binder.getCallingUid();final long origId = Binder.clearCallingIdentity();//继续调用attachApplicationLocked(thread, callingPid, callingUid, startSeq);Binder.restoreCallingIdentity(origId);}}private final boolean attachApplicationLocked(IApplicationThread thread,int pid, int callingUid, long startSeq) {//...//这里调用ApplicationThread的bindApplication方法,最后会执行到//ActivityThread的handleBindApplication方法去创建application,//注册providers,想看可以自己再跟一下thread.bindApplication(processName, appInfo, providers,app.instr.mClass,profilerInfo, app.instr.mArguments,app.instr.mWatcher,app.instr.mUiAutomationConnection, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.persistent,new Configuration(getGlobalConfiguration()), app.compat,getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, isAutofillCompatEnabled);//...// See if the top visible activity is waiting to run in this process...if (normalMode) {try {//这个方法就会执行到realStartActivityLocked方法,之后就和我们知道的一样了if (mStackSupervisor.attachApplicationLocked(app)) {didSomething = true;}} catch (Exception e) {Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);badApp = true;}}//...return true;}
  • Process.java

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) {//调用ZygoteProcess的start方法return zygoteProcess.start(processClass, niceName, uid, gid, gids,runtimeFlags, mountExternal, targetSdkVersion, seInfo,abi, instructionSet, appDataDir, invokeWith, zygoteArgs);}
  • ZygoteProcess.java

    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 {//继续调用startViaZygotereturn startViaZygote(processClass, niceName, uid, gid, gids,runtimeFlags, mountExternal, targetSdkVersion, seInfo,abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,zygoteArgs);} catch (ZygoteStartFailedEx ex) {Log.e(LOG_TAG,"Starting VM process through Zygote failed");throw new RuntimeException("Starting VM process through Zygote failed", ex);}}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 {//...synchronized(mLock) {//openZygoteSocketIfNeeded方法与Zygote的本地Socket建立链接//zygoteSendArgsAndGetResult方法与Zygote的本地socket链接发送信息。return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);}}
  • 接下来是从ActivityThread的main方法如何绑定applicationThread,再如何启动activity的。ActivityThread.java

    public static void main(String[] args) {//...ActivityThread thread = new ActivityThread();//调用attach方法thread.attach(false, startSeq);//...}private void attach(boolean system, long startSeq) {//...if (!system) {//非系统应用//...final IActivityManager mgr = ActivityManager.getService();try {//通过binder联系AMS绑定applicationmgr.attachApplication(mAppThread, startSeq);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}//...} else {//....}}

三、流程总结

  1. 不论从哪启动都是调用Activity的startActivityForResult方法;
  2. 从Instrumentation类的execStartActivity方法获取AMS的客户端通过binder调用AMS的startActivity;
  3. AMS中真正负责调度启动activity的是ActivityStackSupervisor类,28之前直接从这个类就会调到ApplicationThread通过handler与ActivityThread通信,28重构后新增加了一些类但是实际原理没变;
  4. 通过ActivityThread的performLaunchActivity调用到Instrumentation去newActivity,构建上下文,最后通过Instrumentation的callActivityOnCreate调用到activity的真正生命周期;
  5. 如果从Launcher启动activity的流程与上面基本一致,只是需要先去用Zygote进程fork出新的app进程,然后再启动指定的activity。

Activity的启动流程源码解析相关推荐

  1. Android基础四大组件之Activity的启动过程源码解析

    前言 Activity是Android中一个很重要的概念,堪称四大组件之首,关于Activity有很多内容,比如生命周期和启动Flags,这二者想要说清楚,恐怕又要写两篇长文,更何况分析它们的源码呢. ...

  2. NioEventLoop启动流程源码解析

    NioEventLoop的启动时机是在服务端的NioServerSocketChannel中的ServerSocketChannel初始化完成,且注册在NioEventLoop后执行的, 下一步就是去 ...

  3. Kernel启动流程源码解析 1 head.S

    bootloader在跳转到kernel前,需要确保如下设置: MMU = off, D-cache = off, I-cache = on or off x0 = physical address ...

  4. SpringSecurity启动流程源码解析

    前面两期我讲了SpringSecurity认证流程和SpringSecurity鉴权流程,今天是第三期,是SpringSecurity的收尾工作,讲SpringSecurity的启动流程. 就像很多电 ...

  5. Kernel启动流程源码解析 2 head.S

    __cpu_setup.定义kernel\arch\arm64\mm\proc.S中. #define MAIR(attr, mt)    ((attr) << ((mt) * 8)) / ...

  6. Android Launcher启动应用程序流程源码解析

    带着问题看源码 点击桌面Launcher图标后做了哪些工作? 应用程序什么时候被创建的? Application和MainActivity的onCreate()方法什么时候被调用的? 概述 在Andr ...

  7. Activity启动流程源码分析-浅析生命周期函数

    源码分析 接着上一篇 Activity启动流程源码分析-setContentView源码阅读 的讲解,本节介绍一下Activity的生命周期函数何时被调用 要看Activity的生命周期函数何时被调用 ...

  8. Doris FE启动流程源码详细解析

    Doris FE启动流程源码详细解析 一.简介 Apache Doris是一个现代化的MPP分析型数据库产品.仅需亚秒级响应时间即可获得查询结果,有效地支持实时数据分析.Apache Doris的分布 ...

  9. Activity启动流程源码分析(基于Android N)

    Activity启动流程源码分析 一个Activity启动分为两种启动方式,一种是从Launcher界面上的图标点击启动,另一种是从一个Activity中设置按钮点击启动另外一个Activity.这里 ...

  10. swoole 启动流程_EasySwoole 服务启动过程以及主体设计流程源码解析

    EasySwoole 服务启动过程以及主体设计流程源码解析 本文主要讲解EasySwoole 服务的启动过程,会通过源码片段讲解主体的设计流程 命令启动 当我们通过php easyswoole sta ...

最新文章

  1. Win2003用NAT实现ADSL共享与×××服务器
  2. 27 多进程之进程池Pool
  3. akka actor java_Akka:使用非默认构造函数在Scala中定义一个actor并从Java代码创建它 - java...
  4. 最近微信方面的更新   getUserInfo:fail scope unauthorized
  5. 前端学习(760):对象导读
  6. 父子继承与方法的重写 java 114818255
  7. vue + vue-router + vue-resource 基于vue-cli脚手架 ---笔记
  8. Mac安装MySQLWorkbench
  9. VC 在对话框中增加菜单栏
  10. C++ 字符串复制函数substr
  11. SpringCloud Stream操作消息队列
  12. spring5.0学习笔记3
  13. git工作流学习记录
  14. 【图像处理技术】 | 黑科技解读 之 PS检测、弯曲拉平、切边增强、摩尔纹
  15. [JavaScript]45 Fresh Useful JavaScript and jQuery Techniques and Tools
  16. VMware workstation搭建华为FusionCompute实验环境(二)保姆级安装教程,可运行虚拟机
  17. GC5958三相无刷(BLDC)无感正弦波电机驱动芯片 替代APX9358
  18. 什么是计算机动画设计,什么是计算机动画制作
  19. JavaScript-最大值和最小值的方法,正无穷和负无穷的表示方法
  20. 【华人学者风采】韩竹 休斯顿大学

热门文章

  1. 设置linux中docker中的mysql开机自动启动
  2. sublimetext能编辑html语言,SublimeText_编辑保存的Html乱码问题解决
  3. tomcat如何增大并发_高并发环境下如何优化Tomcat性能
  4. 不同项目的测试计划可以复用吗_【app测试计划】移动app测试项目实践.doc
  5. 高级python_高级Python功能
  6. html mysql查询_mysql查询
  7. python设置excel的格式_python 操作Excel 设置格式
  8. SQL:postgresql中,将geometry转换为geojson数据
  9. Vue:进入组件显示蒙版及文字,离开隐藏
  10. EasyUI:中datagrid数据表格的删除、编辑、保存、撤销功能实现