Application.onCreate
Application.onCreate() 不是应用进程的第一段应用代码。LoadedApk.makeApplicationInner() 先确定当前 process 对应的 Application 类、建立 classloader 和 ContextImpl,通过 Instrumentation/AppComponentFactory 实例化对象并调用 attachBaseContext();ActivityThread 随后先安装 ContentProvider,再执行 Instrumentation.onCreate,最后才调用 Application.onCreate()。
1. 类选择
源码文件:frameworks/base/core/java/android/app/LoadedApk.java
String processName = Process.myProcessName();
String appClass = mApplicationInfo
.getCustomApplicationClassNameForProcess(
processName);
if (forceDefaultAppClass || appClass == null) {
appClass = "android.app.Application";
}Android 17 支持按 process 选择自定义 Application 类;restricted backup 等路径可以强制基础 android.app.Application。选择发生在 classloader 创建前,错误类名会在实例化阶段暴露。
2. LoadedApk缓存
if (mApplication != null) {
return mApplication;
}
synchronized (sApplications) {
Application cached =
sApplications.get(mPackageName);
if (cached != null && !allowDuplicateInstances) {
mApplication = cached;
return cached;
}
}LoadedApk 保存 mApplication,进程级 sApplications 又按 package name 缓存实例。framework 内部 makeApplicationInner 默认拒绝重复实例;隐藏 API 的兼容路径可能允许重复。system_server 的 android package 有特殊历史情况,源码只对非 android 包记录重复 WTF。
3. 类加载与资源
ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
initializeJavaContextClassLoader();
}
SparseArray<String> packageIdentifiers =
getAssets().getAssignedPackageIdentifiers(
false, false);
for (...) {
rewriteRValues(cl, packageName, id);
}应用 classloader 和线程 context classloader 在实例化前准备;共享库 APK 的 R 常量按运行时 package id 重写。rewriteRValues 找不到 R 类或 callback 时可以跳过,反射调用错误才会影响应用创建。
4. Context绑定
源码文件:frameworks/base/core/java/android/app/LoadedApk.java、frameworks/base/core/java/android/app/Instrumentation.java、frameworks/base/core/java/android/app/Application.java
ContextImpl appContext = ContextImpl.createAppContext(
mActivityThread, this);
NetworkSecurityConfigProvider
.handleNewApplication(appContext);
Application app = mActivityThread.mInstrumentation
.newApplication(cl, appClass, appContext);
appContext.setOuterContext(app);Instrumentation 的 newApplication() 继续把 classloader、类名和 Context 交给 AppComponentFactory;返回 Application 后,attachBaseContext() 才有机会运行。
public Application newApplication(
ClassLoader cl, String className,
Context context) throws Exception {
Application app = getFactory(
context.getPackageName())
.instantiateApplication(cl, className);
app.attach(context);
return app;
}newApplication() 返回前已经完成 framework 内部 attach;Application 的 attach 实现再把开发者可见的 base context 与 LoadedApk 关联起来。
final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}Application.attach() 完成上下文绑定后,LoadedApk 才会登记 Application 实例:
AppComponentFactory/Instrumentation 负责实例化,随后 Application.attach() 调用开发者可覆盖的 attachBaseContext(),再保存 LoadedApk。此时 Application 对象已存在,但 onCreate() 尚未调用。
5. 实例登记
mActivityThread.addApplication(app);
mApplication = app;
if (!allowDuplicateInstances) {
synchronized (sApplications) {
sApplications.put(mPackageName, app);
}
}Application 加入 ActivityThread 和 LoadedApk 缓存后,其他 framework 代码可以通过进程/包状态取到它。登记完成并不表示 Provider 或 onCreate 已完成。
6. Provider时序
源码文件:frameworks/base/core/java/android/app/ActivityThread.java
Application app = data.info.makeApplicationInner(
data.restrictedBackupMode, null);
mInitialApplication = app;
if (!data.restrictedBackupMode
&& !ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
}
mInstrumentation.onCreate(
data.instrumentationArgs);
mInstrumentation.callApplicationOnCreate(app);Provider 在 Application.onCreate 前安装。原因是系统需要在进程绑定期间发布 provider Binder/本地对象,Provider 自身可能依赖 Application context,但不能假设 Application.onCreate 已运行。restricted backup 路径跳过 Provider,避免自定义 Application/provider 副作用。
7. onCreate调用
源码文件:frameworks/base/core/java/android/app/Instrumentation.java
public void callApplicationOnCreate(
Application app) {
app.onCreate();
}默认 Instrumentation 直接调用 Application.onCreate;测试 Instrumentation 可在调用前后插入逻辑。ActivityThread 捕获异常并调用 mInstrumentation.onException(app, e);返回 false 时包装为“Unable to create application”并终止绑定,返回 true 表示 Instrumentation 已处理异常。
8. AMS完成边界
Application.onCreate 返回后,ActivityThread 才执行字体预加载等收尾并调用:
mgr.finishAttachApplication(
mStartSeq,
timestampApplicationOnCreateNs);因此 AMS 看到 attachApplication 不代表 Application ready;finishAttachApplication 才带着 onCreate timestamp 标记绑定完成。Application.onCreate 后进程可能仍未启动首个 Activity/Service/Receiver。
9. 失败与性能边界
- attachBaseContext 异常:Application 尚未登记;
- AppComponentFactory/classloader 异常:实例化失败;
- Provider onCreate 卡住:Application.onCreate 尚未执行;
- Instrumentation.onCreate 异常:Application 已创建、Provider 可能已安装;
- Application.onCreate 异常:由 Instrumentation.onException 决定是否继续;
- onCreate 很慢:阻塞
finishAttachApplication和组件启动; - 第三方 SDK 放在 onCreate:会增加所有使用该进程的冷启动关键路径。
10. 导航与后续
# LoadedApk 的 Application 类、缓存、Context 和 Instrumentation 实例化。
rg -n "makeApplicationInner|getCustomApplicationClassNameForProcess|getClassLoader|rewriteRValues|createAppContext|newApplication|sApplications" \
frameworks/base/core/java/android/app/LoadedApk.java
# attachBaseContext 和 onCreate 调用。
rg -n "newApplication|callApplicationOnCreate|attachBaseContext|final void attach" \
frameworks/base/core/java/android/app/Instrumentation.java \
frameworks/base/core/java/android/app/Application.java
# Provider/Application/finishAttach 的真实顺序。
rg -n "makeApplicationInner|installContentProviders|Instrumentation.onCreate|callApplicationOnCreate|finishAttachApplication" \
frameworks/base/core/java/android/app/ActivityThread.java下一篇将进入进程 specialization,分析 uid/gid、mount namespace、SELinux、seccomp 和 runtime flags 如何在进入 ActivityThread 前生效;不会重复 Application 生命周期。
