App启动——Application的创建

本文详细解释了Android应用启动时Application对象的创建流程,涉及主线程、ActivityThread、ActivityManagerService和Instrumentation等关键类的交互。重点介绍了bindApplication方法和Application对象的初始化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Application的创建

一个 app 启动时候创建一个 Application 对象。这个对象的创建时间在 frameworks 中调用创建的,创建流程可见下图,涉及的几个主要的类调用。

Application创建流程

一、主线程运行入口

​ APP进程起来后,主线程运行入库 ActivityThread.main() 方法。

    ```java
    // ActivityThread.java
    
    @UnsupportedAppUsage
    final ApplicationThread mAppThread = new ApplicationThread();
    
    public static void main(String[] args) {
    	// ...
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);
        // ...
    }
    
    @UnsupportedAppUsage
    private void attach(boolean system, long startSeq) {
        // ...
    
        if (!system) {
            // ...
    
            final IActivityManager mgr = ActivityManager.getService(); //获取 IActivityManager 对象。
            try {
                mgr.attachApplication(mAppThread, startSeq); // Binder 调用 AMS 的 attachApplicaion() 方法。
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
    		// ...
        }
    
        // ...
    }
    ```

运行启动是一般的app,并非 system app,因此进入到 if 分支。

二、ActivityManagerService 方法执行

从app主线程执行,进而跨进程调用到 ActivityManagerServiceattachApplication(IApplicationThread thread, long startSeq) 方法。

// ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
    if (thread == null) {
        throw new SecurityException("Invalid application interface");
    }
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}

@GuardedBy("this")
private void attachApplicationLocked(@NonNull IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
	// ......  这里的一个比较重要的数据是 appInfo:ApplicationInfo
    // if 分支内,表明运行的时候隔离状态的app,这样的app不能访问系统资源,服务及其他app进程。
    if (app.getIsolatedEntryPoint() != null) {
        // This is an isolated process which should just call an entry point instead of
        // being bound to an application.
        thread.runIsolatedEntryPoint(
                app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());
    } else if (instr2 != null) {
        thread.bindApplication(processName, appInfo,
                app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
                providerList,
                instr2.mClass,
                profilerInfo, instr2.mArguments,
                instr2.mWatcher,
                instr2.mUiAutomationConnection, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.getCompat(), getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions,
                app.getDisabledCompatChanges(), serializedSystemFontMap,
                app.getStartElapsedTime(), app.getStartUptime());
    } else {
        thread.bindApplication(processName, appInfo,
                app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
                providerList, null, profilerInfo, null, null, null, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.getCompat(), getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions,
                app.getDisabledCompatChanges(), serializedSystemFontMap,
                app.getStartElapsedTime(), app.getStartUptime());
    }
	// ......
}

在内部调用到 attachApplicationLocked() 方法,在方法内部,会执行到 bindApplication() 方法,除非运行的app是一个独立APP,即不访问系统任何资源。这个方法里还有一个重要的数据变量是 appInfo 表示了应用的信息,会在调用 bindApplication() 方法时传递给 ApplicationThread 对象方法。

三、ApplicationThread.bindApplication()

// ActivityThread.java

private class ApplicationThread extends IApplicationThread.Stub {
    @Override
    public final void bindApplication(String processName, ApplicationInfo appInfo,
            String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage,
            ProviderInfoList providerList, 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, long[] disabledCompatChanges,
            SharedMemory serializedSystemFontMap,
            long startRequestedElapsedTime, long startRequestedUptime) {
        // ......
        
            AppBindData data = new AppBindData();
            // 构建 AppBindData 数据结构。
            updateCompatOverrideScale(compatInfo);
            CompatibilityInfo.applyOverrideScaleIfNeeded(config);
            sendMessage(H.BIND_APPLICATION, data);  // 发送消息。
    }
}

ActivityManagerService 中进行执行后,获取必要的信息,然后执行回到 ApplicationThread 的 app 进程 bindApplication() 方法中,并构建 AppBindData 数据对象,最终发送消息 H.BIND_APPLICATION 进入消息队列等待执行。

四、handleBindApplication(AppBindData data)

通过消息机制执行到 handleMessage(Message msg),依据消息 whatBIND_APPLICATION 执行方法 handleBindApplication(AppBindData data)

// ActivityThread.java

@UnsupportedAppUsage
private void handleBindApplication(AppBindData data) {
	// ...
    // 获取 LoadedApk 类型对象 
    data.info = getPackageInfo(data.appInfo, mCompatibilityInfo, null /* baseLoader */,  
    							false /* securityViolation */, true /* includeCode */,
    							false /* registerPackage */, isSdkSandbox);
    
    // ...
    // 获取 ActivityManagerService 的 Binder 句柄
    final IActivityManager mgr = ActivityManager.getService();   
    // 创建 Context 上下文对象
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);    
    
    // ...
    Application app;
    // ...
        try {
			// 通过 LoadedApk 对象创建 Application 对象,内部具体实现细节,并且调用到了 Application.attach(Coext)。
		    // 在 attach(Context) 方法内调用从 ContextWrapper 继承而来的 attachBaseContext(Context),设置 mBaseContext 的实例变量。 
            app = data.info.makeApplicationInner(data.restrictedBackupMode, null);
            // ...
        } finally {
            // ...
        }
		// ...
        try {
            mgr.finishAttachApplication(mStartSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
}

执行 handleBindApplication() 方法传入参数 AppBindData ,在最终创建 Application 前,data.info 被赋值 。接着调用到 LoadedApk.makeApplicationInner(boolean forceDefaultAppClass, Instrumentation instrumentation)

// LoadedApk.java

public Application makeApplicationInner(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    return makeApplicationInner(forceDefaultAppClass, instrumentation,
            /* allowDuplicateInstances= */ false);
}

private Application makeApplicationInner(boolean forceDefaultAppClass,
        Instrumentation instrumentation, boolean allowDuplicateInstances) {
    if (mApplication != null) {
        return mApplication;
    }

	// ...
    Application app = null;

    final String myProcessName = Process.myProcessName();
    String appClass = mApplicationInfo.getCustomApplicationClassNameForProcess(
            myProcessName);
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }

    try {
        final java.lang.ClassLoader cl = getClassLoader();
		// ...
        // 创建方式与 ActivityThread 中 handleBindApplication 创建方式一致。
        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;
	// ...
    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app); // 调用了 Application 的声明周期方法 onCreate
        } catch (Exception e) {
           // ...
        }
    }
    return app;
}

最终调用的 Application 对象是在 Instrumentation 中创建。

### Android 应用程序启动流程 Android 应用的启动是一个复杂的过程,涉及多个组件之间的交互。以下是应用启动的主要阶段及其描述: #### 1. **Launcher 发起 Intent** 当用户点击应用程序图标时,Launcher 将发送一个 `Intent` 给系统的 ActivityManagerService (AMS),该 `Intent` 包含目标活动(Activity)的信息[^1]。 #### 2. **Zygote 创建进程** AMS 接收到请求后会检查目标应用是否已经运行在一个现有的进程中。如果未找到,则 AMS 请求 Zygot 进程创建一个新的虚拟机实例并加载必要的库文件。 #### 3. **Application 对象初始化** 新进程被创建之后,系统调用 Application 类的构造函数以及其子类中的 `onCreate()` 方法完成全局上下文环境设置工作[^3]。 #### 4. **Activity 加载与显示** 随后进入主线程执行栈中第一个待处理的任务——即我们定义的第一个 activity 的生命周期方法链:从 attach 到 window decor view inflation 再到最终绘制界面给用户看整个过程都需要耗费一定时间资源去完成操作。 ### 常见启动问题及解决方案 #### 性能优化建议 为了提高用户体验,在实际开发过程中需要注意以下几个方面可能影响到冷热启速度的因素,并采取相应措施加以改进: - **减少不必要的依赖注入框架** 如果项目里引入了很多第三方库来做DI(比如 Dagger,Hilt),那么这些工具本身也会增加额外开销,尤其是在第一次打开的时候因为它们需要解析配置文件等等动作都会延长耗时. - **延迟非必要逻辑至后台线程或者后续时机再做** 把一些不紧急但又必须做的事情安排在稍后的时刻去做而不是放在app刚起来就马上干掉它这样可以有效降低首屏渲染所需的时间成本从而让页面更快呈现出来供访问者查看内容. - 使用 TraceView 工具定位瓶颈所在位置以便针对性修复性能缺陷等问题 ```java @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); // Example of delaying non-critical tasks to background thread. new Thread(() -> { heavyTask(); }).start(); setContentView(R.layout.activity_main); } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虚妄皆空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值