type
status
date
slug
summary
tags
category
icon
password
之前也写过Application启动流程之类的文章,但是总感觉这个程度不够,再来总结下.
先把脑子里那一堆忘掉,想一想要启动一个Application需要干什么:
- 需要知道app可执行文件的位置
即apk中的dex文件,或者经过dexopt优化过后的dex文件,在APK安装的时候信息已经被记录在了手机上.
- 创建app进程
Android是基于Linux的,创建进程的方式一般有两种,fork和exec,在Android中应用进程都是从zygote进程fork的.
- 进程创建了得执行一个main()入口方法,把应用跑起来
main()入口在
ActivityThread
中- Android还比较特殊,需要启动一个主界面,即Launch Activity
APK安装时已经把Activity的各种信息保存了,因此找到对应APP的Launch Activity即可
再把流程走一遍吧!
点击桌面上的App Icon
Launcher 应用中 点击APP Icon之后会调用:
// 启动目标APP startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher, sourceContainer == null ? CONTAINER_ALL_APPS: sourceContainer); private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher, @Nullable String sourceContainer) { Intent intent; intent = item.getIntent(); launcher.startActivitySafely(v, intent, item, sourceContainer); }
Launcher中有:
public boolean startActivitySafely(View v, Intent intent, ItemInfo item, @Nullable String sourceContainer) { boolean success = super.startActivitySafely(v, intent, item, sourceContainer); if (success && v instanceof BubbleTextView) { BubbleTextView btv = (BubbleTextView) v; btv.setStayPressed(true); addOnResumeCallback(btv); } return success; }
最终还是会调用到
startActivity()
Activity#startActivity()
activity.startActivity()
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } } }
这里的
mMainThread
即是ActivityThread
,不过不是目标应用的ActivityThread.后面依次经历如下类的调用:
- Instrumentation#execStartActivity()
- ActivityTaskManagerService#startActivityAsUser()
- ActivityStartController#obtainStarter()
- ActivityStarter#startActivity() -> ActivityStarter#startActivityUnchecked()
- RootActivityContainer#resumeFocusedStacksTopActivities()
- ActivityStack#resumeTopActivityUncheckedLocked() -> ActivityStack#resumeTopActivityInnerLocked()
- ActivityStackSupervisor#startSpecificActivityLocked()
- 目标app如果有线程正在运行,则ActivityStackSupervisor#realStartActivityLocked()
- 目标app如果没有线程在运行,则会发送一个Handler Message,调用ActivityManagerInternal#startProcess()
启动app进程
从
ActivityManagerInternal#startProcess()
方法开始看:/** Starts a given process. */ public abstract void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead, String hostingType, ComponentName hostingName);
在
ActivityManagerService
中有一个内部类LocalService
就是继承的ActivityManagerInternal
,因此看一下startProcess的实现方法:@Override public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead, String hostingType, ComponentName hostingName) { synchronized (ActivityManagerService.this) { //传入了进程名字,目标进程的applicationInfo,activity的组件名 startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */, new HostingRecord(hostingType, hostingName), false /* allowWhileBooting */, false /* isolated */, true /* keepIfLarge */); } } final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord, boolean allowWhileBooting, boolean isolated, boolean keepIfLarge) { // 这里的mProcessList专门处理app 进程相关的逻辑 return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */); }
到
ProcessList
中看下:final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord, boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) { long startTime = SystemClock.elapsedRealtime(); ProcessRecord app; // 根据进程名和uid,获取进程信息,ProcessList中有一个Map存储了processName,uid到ProcessRecord的映射 // 获取的是正在运行的进程的信息,如果之前没运行过这里当然是null app = getProcessRecordLocked(processName, info.uid, keepIfLarge); checkSlow(startTime, "startProcess: after getProcessRecord"); if (app != null && app.pid > 0) { ProcessList.killProcessGroup(app.uid, app.pid); mService.handleAppDiedLocked(app, true, true); } if (app == null) { // 创建新的ProcessRecord app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord); app.crashHandler = crashHandler; app.isolatedEntryPoint = entryPoint; app.isolatedEntryPointArgs = entryPointArgs; } else { // If this is a new package in the process, add the package to the list app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats); } // 关键:启动app进程 final boolean success = startProcessLocked(app, hostingRecord, abiOverride); return success ? app : null; }
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord, boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride) { // abi String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi; if (requiredAbi == null) { requiredAbi = Build.SUPPORTED_ABIS[0]; } // 指令集 String instructionSet = null; if (app.info.primaryCpuAbi != null) { instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi); } // 启动进程,进程的入口在ActivityThread.启动成功返回新进程的pid,否则抛出异常 final String entryPoint = "android.app.ActivityThread"; // 实际启动 return startProcessLocked(hostingRecord, entryPoint, app, uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startTime); } catch (RuntimeException e) { // 进程启动失败,清理相关数据 mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false, false, true, false, false, app.userId, "start failure"); return false; } }
这里默认是异步的方式启动进程,即在一个单独的线程中启动进程:
// service是ActivityManagerService,handler是一个ServiceThread(HandlerThread)中的handler mService.mProcStartHandler.post(() -> { // 启动进程 final Process.ProcessStartResult startResult = startProcess(app.hostingRecord, entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime); synchronized (mService) { handleProcessStartedLocked(app, startResult, startSeq); } });
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal, String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime) { // 启动进程 startResult = Process.start(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, app.info.packageName, new String[] {PROC_START_SEQ_IDENT + app.startSeq}); }
其实这个方法里有一个判断,即regular_zygote,app_zygote,webview_zygote.其实这三个判断,在HostingRecord中可以简单的看出来区别:
- regular_zygote,一般是各种Activity的启动时候用的
- app_zygote,一般是各种Service启动的时候用的
- webview_zygote,当然是webview用的
后面就进入了
Process
中了:public static ProcessStartResult start(@NonNull final String processClass, @Nullable final String niceName, int uid, int gid, @Nullable int[] gids, int runtimeFlags, int mountExternal, int targetSdkVersion, @Nullable String seInfo, @NonNull String abi, @Nullable String instructionSet, @Nullable String appDataDir, @Nullable String invokeWith, @Nullable String packageName, @Nullable String[] zygoteArgs) { // ZYGOTE_PROCESS是ZygoteProcess,processClass,即前面传入的ActivityThread,niceName是包名 return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, /*useUsapPool=*/ true, zygoteArgs); }
private Process.ProcessStartResult startViaZygote(@NonNull final String processClass, @Nullable final String niceName, final int uid, final int gid, @Nullable final int[] gids, int runtimeFlags, int mountExternal, int targetSdkVersion, @Nullable String seInfo, @NonNull String abi, @Nullable String instructionSet, @Nullable String appDataDir, @Nullable String invokeWith, boolean startChildZygote, @Nullable String packageName, boolean useUsapPool, @Nullable String[] extraArgs) throws ZygoteStartFailedEx { ArrayList<String> argsForZygote = new ArrayList<>(); // --runtime-args, --setuid=, --setgid=, // and --setgroups= must go first argsForZygote.add("--runtime-args"); argsForZygote.add("--setuid=" + uid); argsForZygote.add("--setgid=" + gid); argsForZygote.add("--runtime-flags=" + runtimeFlags); if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) { argsForZygote.add("--mount-external-default"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) { argsForZygote.add("--mount-external-read"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) { argsForZygote.add("--mount-external-write"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_FULL) { argsForZygote.add("--mount-external-full"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_INSTALLER) { argsForZygote.add("--mount-external-installer"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_LEGACY) { argsForZygote.add("--mount-external-legacy"); } argsForZygote.add("--target-sdk-version=" + targetSdkVersion); // --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); } if (invokeWith != null) { argsForZygote.add("--invoke-with"); argsForZygote.add(invokeWith); } if (startChildZygote) { argsForZygote.add("--start-child-zygote"); } if (packageName != null) { argsForZygote.add("--package-name=" + packageName); } // 入口:"android.app.ActivityThread" argsForZygote.add(processClass); if (extraArgs != null) { Collections.addAll(argsForZygote, extraArgs); } synchronized(mLock) { // 如果不使用系统图形驱动,则不会使用usap pool return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), useUsapPool, argsForZygote); } }
这里的
USAP
就是unspecialized app process 的意思.这里分两步:
- 打开zygote 的socket 连接
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { try { // 连接到64位的zygote socket attemptConnectionToPrimaryZygote(); if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } if (mZygoteSecondarySocketAddress != null) { // 打开32位的zygote socket attemptConnectionToSecondaryZygote(); if (secondaryZygoteState.matches(abi)) { return secondaryZygoteState; } } } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to zygote", ioe); } throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); }
对于Android而言,这里首先会尝试打开64位的zygote socket,如果失败才会尝试32位的zygote.然后返回一个连接状态ZygoteState.
不管是64位还是32位的zygote socket,过程都是一样的:
private void attemptConnectionToPrimaryZygote() throws IOException { if (primaryZygoteState == null || primaryZygoteState.isClosed()) { // mZygoteSocketAddress 即 名为"zygote"的LocalSocketAddress primaryZygoteState = ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress); maybeSetApiBlacklistExemptions(primaryZygoteState, false); maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState); maybeSetHiddenApiAccessStatslogSampleRate(primaryZygoteState); } } private void attemptConnectionToSecondaryZygote() throws IOException { if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { // "zygote_secondary" secondaryZygoteState = ZygoteState.connect(mZygoteSecondarySocketAddress, mUsapPoolSecondarySocketAddress); // 对一些API的调用做一些限制 maybeSetApiBlacklistExemptions(secondaryZygoteState, false); maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState); maybeSetHiddenApiAccessStatslogSampleRate(secondaryZygoteState); } }
具体的连接过程看下面:
static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress, @Nullable LocalSocketAddress usapSocketAddress) throws IOException { // 输入输出流 DataInputStream zygoteInputStream; BufferedWriter zygoteOutputWriter; // zygote使用的是LocalSocket final LocalSocket zygoteSessionSocket = new LocalSocket(); try { // 连接socket zygoteSessionSocket.connect(zygoteSocketAddress); // 绑定对应的输入输出流 zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream()); zygoteOutputWriter = new BufferedWriter( new OutputStreamWriter(zygoteSessionSocket.getOutputStream()), Zygote.SOCKET_BUFFER_SIZE); } catch (IOException ex) { try { zygoteSessionSocket.close(); } catch (IOException ignore) { } throw ex; } // 将输入输出流等信息封装到ZygoteState中 return new ZygoteState(zygoteSocketAddress, usapSocketAddress, zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter, getAbiList(zygoteOutputWriter, zygoteInputStream)); }
到这里已经建立起了和zygote的local socket连接.
- 通过建立的local socket 连接发送命令并且返回结果
这里发送的命令都在前面组装的
argsForZygote
中,在这里其实就是使用zygote 启动(fork) 指定的进程的命令.private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult( ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx { try { final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter; final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream; zygoteWriter.write(msgStr); zygoteWriter.flush(); // fork结果 Process.ProcessStartResult result = new Process.ProcessStartResult(); // fork进程成功,返回进程的pid result.pid = zygoteInputStream.readInt(); result.usingWrapper = zygoteInputStream.readBoolean(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } return result; } catch (IOException ex) { zygoteState.close(); Log.e(LOG_TAG, "IO Exception while communicating with Zygote - " + ex.toString()); throw new ZygoteStartFailedEx(ex); } }
经历了这些步骤之后,app 进程也就创建成功了,再来看下zygote具体是如何响应fork请求的.
Zygote fork app进程
ZygoteServer和ZygoteConnection中会收到socket请求,并做对应的处理:
// 这个parsedArgs就是上面传入的各种启动参数 pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote, parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
到Zygote中看看:
public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, int targetSdkVersion) { ZygoteHooks.preFork(); // 调用native方法fork app进程,niceName是进程名 int pid = nativeForkAndSpecialize( uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, appDataDir); // 返回0,表示此时是子进程执行,即app进程 if (pid == 0) { Zygote.disableExecuteOnly(targetSdkVersion); } ZygoteHooks.postForkCommon(); return pid; }
到
frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
中看看:// nice_name是进程名 static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app) { // fork操作 pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true); // 子进程,即app 进程执行下面的逻辑 // 这里主要是设置线程名等逻辑 if (pid == 0) { SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities, mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE, instruction_set, app_data_dir, is_top_app == JNI_TRUE); } return pid; }
进程fork之后,会执行下面的逻辑(ZygoteConnection.java中):
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, boolean isZygote) { // 设置进程名 if (parsedArgs.mNiceName != null) { Process.setArgV0(parsedArgs.mNiceName); } // 最初传参没有带这个参数 if (parsedArgs.mInvokeWith != null) { WrapperInit.execApplication(parsedArgs.mInvokeWith, parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion, VMRuntime.getCurrentInstructionSet(), pipeFd, parsedArgs.mRemainingArgs); throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned"); } else { if (!isZygote) { // 普通app会走这个分支 return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); } else { return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); } } }
再来看一下
ZygoteInit
:public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { RuntimeInit.commonInit(); ZygoteInit.nativeZygoteInit(); return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); }
这个方法里干了很多重要的事情:
- 设置异常处理的逻辑和一些崩溃日志的输出逻辑
protected static final void commonInit() { // 应用到VM中的所有线程,pre handler不可替换,default handler可以替换 LoggingHandler loggingHandler = new LoggingHandler(); RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler); // 我们常见的异常处理 Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler)); }
private static class LoggingHandler implements Thread.UncaughtExceptionHandler { public volatile boolean mTriggered = false; @Override public void uncaughtException(Thread t, Throwable e) { if (mApplicationObject == null && (Process.SYSTEM_UID == Process.myUid())) { Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e); } else { // 这里就是我们最常见的崩溃信息 StringBuilder message = new StringBuilder(); // The "FATAL EXCEPTION" string is still used on Android even though // apps can set a custom UncaughtExceptionHandler that renders uncaught // exceptions non-fatal. message.append("FATAL EXCEPTION: ").append(t.getName()).append("\\n"); final String processName = ActivityThread.currentProcessName(); if (processName != null) { message.append("Process: ").append(processName).append(", "); } message.append("PID: ").append(Process.myPid()); Clog_e(TAG, message.toString(), e); } } }
具体的异常捕获话题就不在这里写了,偏题了.
- 找到ActivityThread的入口方法,并反射调用
protected static Runnable applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { // 设置APP内存使用上限和targetSdkVersion VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); final Arguments args = new Arguments(argv); // 找到ActivityThread的main方法 return findStaticMain(args.startClass, args.startArgs, classLoader); } protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) { 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 { // 获取到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); } // 包装到一个Runnable中 return new MethodAndArgsCaller(m, argv); }
static class MethodAndArgsCaller implements Runnable { /** method to call */ private final Method mMethod; /** argument array */ private final String[] mArgs; public MethodAndArgsCaller(Method method, String[] args) { mMethod = method; mArgs = args; } public void run() { try { // 执行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); } } }
到这里ActivityThread.main()就被成功执行了.
那么实际上这个返回的Runnable是谁运行的,在什么线程里运行的呢?
答案是在
ZygoteServer
的runSelectLoop
方法中会再处理一下,最后交由ZygoteInit去执行.ActivityThread.main()
public static void main(String[] args) { //主线程 Looper Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); // 关键方法,会将APP的Application对象与这个新的app进程联系起来 thread.attach(false, startSeq); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
最为关键的调用就是attach方法:
// mgr就是ActivityManagerService final IActivityManager mgr = ActivityManager.getService(); try { mgr.attachApplication(mAppThread, startSeq); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); }
然后会调用到
ApplicationThread
中的bindApplication()
方法:public final void bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, ProfilerInfo profilerInfo, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableBinderTracking, boolean trackAllocation, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map services, Bundle coreSettings, String buildSerial, AutofillOptions autofillOptions, ContentCaptureOptions contentCaptureOptions) { // 将进程信息封装到AppBindData中,然后利用Handler传输 AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.instrumentationUiAutomationConnection = instrumentationUiConnection; data.debugMode = debugMode; data.enableBinderTracking = enableBinderTracking; data.trackAllocation = trackAllocation; data.restrictedBackupMode = isRestrictedBackupMode; data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; data.buildSerial = buildSerial; data.autofillOptions = autofillOptions; data.contentCaptureOptions = contentCaptureOptions; // H是ApplicationThread中的一个Handler sendMessage(H.BIND_APPLICATION, data); }
这里会发送一个
BIND_APPLICATION
消息,Handler接收到之后会进行处理:private void handleBindApplication(AppBindData data) { // 设置UI线程为敏感线程 VMRuntime.registerSensitiveThread(); // 告诉ART虚拟机进程名 Process.setArgV0(data.processName); VMRuntime.setProcessPackageName(data.appInfo.packageName); // 传递数据目录给ART,用于缓存信息 VMRuntime.setProcessDataDirectory(data.appInfo.dataDir); // data.info 是LoadedApk对象,即表示一个新APK的信息 data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); HardwareRenderer.setPackageName(data.appInfo.packageName); // 创建应用的 context final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); // 硬件加速 setupGraphicsSupport(appContext); mInstrumentation = new Instrumentation(); mInstrumentation.basicInit(this); // 创建Application对象 Application app; // 这里非常重要的是:传入的instrumentation对象为null app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; // 不是backup模式的话,会安装ContentProvider if (!data.restrictedBackupMode) { if (!ArrayUtils.isEmpty(data.providers)) { installContentProviders(app, data.providers); } } // Instrument 测试通常在这个时机启动测试线程,因此在这里onCreate mInstrumentation.onCreate(data.instrumentationArgs); // 调用Application的onCreate()方法 mInstrumentation.callApplicationOnCreate(app); // 预加载字体资源 FontsContract.setApplicationContextForResources(appContext); final ApplicationInfo info = getPackageManager().getApplicationInfo( data.appInfo.packageName, PackageManager.GET_META_DATA /*flags*/, UserHandle.myUserId()); final int preloadedFontsResource = info.metaData.getInt( ApplicationInfo.METADATA_PRELOADED_FONTS, 0); if (preloadedFontsResource != 0) { data.info.getResources().preloadFonts(preloadedFontsResource); } }
这个过程中做了很多事,但是主要就以下这些:
- 告诉ART虚拟机一些信息,比如应用的包名,数据目录等
- 各种调试功能,Profile功能判断与设置
- 告诉虚拟机当前UI线程是敏感线程
- 硬件加速的支持
- 创建LoadedApk对象
- 创建Context对象
- 在创建Application之前,创建Instrumentation,用于监视app与系统的交互
- 创建Application对象
- 安装ContentProvider
- 利用Instrumentation执行Application#onCreate()回调
Application对象的创建
上面已经说过,会调用
LoadedAPk#makeApplication()
方法去创建Application对象:public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { if (mApplication != null) { return mApplication; } Application app = null; String appClass = mApplicationInfo.className; // 默认的Application if (forceDefaultAppClass || (appClass == null)) { appClass = "android.app.Application"; } try { java.lang.ClassLoader cl = getClassLoader(); if (!mPackageName.equals("android")) { // 设置线程的Context ClassLoader initializeJavaContextClassLoader(); } // 创建Context ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); // 创建Application对象 app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); appContext.setOuterContext(app); } catch (Exception e) { //... } mActivityThread.mAllApplications.add(app); mApplication = app; // Rewrite the R 'constants' for all library apks. SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(); final int N = packageIdentifiers.size(); for (int i = 0; i < N; i++) { final int id = packageIdentifiers.keyAt(i); if (id == 0x01 || id == 0x7f) { continue; } rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id); } return app; }
可以看到其实还是调用的Instrumentation去创建Application对象:
public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { Application app = getFactory(context.getPackageName()) .instantiateApplication(cl, className); app.attach(context); return app; }
最后会进入到
AppComponentFactory
中利用ClassLoader去创建Application对象:public @NonNull Application instantiateApplication(@NonNull ClassLoader cl, @NonNull String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException { // 这里的ClassLoader就是LoadedApk的ClassLoader return (Application) cl.loadClass(className).newInstance(); }
到这里Application对象就创建成功了,并且调用了Application的
attach(context)
方法./* package */ final void attach(Context context) { attachBaseContext(context); mLoadedApk = ContextImpl.getImpl(context).mPackageInfo; }
attach
方法子类是不可以重写的,但是attachBaseContext
可以,这里可以看到Application还持有了LoadedApk对象.Application#onCreate()执行
在application对象
attach(context)
之后,Instrumentation会中会调用Application#onCreate()
方法:public void callApplicationOnCreate(Application app) { app.onCreate(); }
其实在调用
Application#onCreate()
之前,可以在Instrumentation
中插入一些钩子逻辑,这个在前面的代码中可以看到端倪:public void onCreate(Bundle arguments) { }
Instrumentation
的onCreate()
是一个空方法,可以实现自己的Instrumentation
以插入一些逻辑,以在应用代码执行前做一些特殊的处理.到这里Application就已经创建完成,并且执行了onCreate了.剩下的就是其中Launcher Activity的流程了,这篇文章源码流程已经够多了,后面单独写一篇文章梳理下Activity的启动流程吧!
总结
- Application其实也是通过ClassLoader加载的
- zygote fork出了进程,但是并不代表执行了ActivityThread的main方法
- zygote是java世界的进程,fork出 app进程之后,app进程也拥有一份拷贝数据
- Instrumentation和LoadedApk在Application的启动过程中很重要,可以利用它做很多事情
- 全局的异常捕获与处理也是在这个阶段设置的
- 堆内存的使用上限也是这个过程设置的
- Context的创建,主线程Looper等都是在这个过程中进行的
- Debug模式,Profile模式的逻辑判断也是在这个过程进行的
- zygote的通信机制:local socket + file descriptor
- 作者:姜康
- 链接:https://jiangkang.tech/article/0c62e7e9-d9fe-4dac-84bd-24e77ee5f7b0
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章