枯燥的源码分析—Application创建过程

1,630 阅读4分钟

概述

在Android应用进程中,每个应用都对应着一个Application。Application的创建于销毁贯穿了整个应用进程的生命周期。所以理解Application的创建过程不仅有利于我们理解应用进程的创建,还能加深对使用Application中的理解。

接下来回从两个进程中来分析Application的创建过程,一个进程是system_server进程,一个是应用进程。这两个进程都在创建的过程中创建了Application。

Application有什么用

我们使用Application一般是在应用进程中使用的。这里先列举下Application的经常用到的场景与职能。

  • 处理应用程序生命周期;通过直接继承Application类,我们可以使用Application的生命周期方法来管理应用进程的生命周期,比如在onCreate()方法中初始化全局资源。
  • 监听Activity生命周期;通过registerActivityLifecycleCallbacks()方法可以注册回调接口监听Activity的生命周期调用。
  • 监听所有组件的回调方法;通过registerComponentCallbacks()方法实现,可以回调Android四大组件的公共方法,常用的有onConfigurationChanged(),onLowMemory()等。
  • 通过Application获取应用资源

system_server中的创建过程

system_server进程是在Android系统启动时创建的一个进程,它的主要作用是启动和管理系统服务,比如我们熟知的AMS、WMS等。

接下来就分析下system_server创建Application的过程以及Application在system_server中起到的作用。

SystemServer的启动方法

system_server的启动是从run()方法开始的。

private void run() { 
    ...
    // Initialize the system context.
    createSystemContext();
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    ...
}

在run()方法中可以看到通过createSystemContext()方法创建了SystemContext。

private void createSystemContext() {
    ActivityThread activityThread = ActivityThread.systemMain();
    mSystemContext = activityThread.getSystemContext();
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

    final Context systemUiContext = activityThread.getSystemUiContext();
    systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}

在createSystemContext()方法中看到了一个熟悉的类ActivityThread。也就是Android主线程的启动类。我们可以看到调用过ActivityThread的systemMain()方法后,获取到了所谓的System Context。

接下来我们把目光转移到ActivityThread中去。

ActivityThread的systemMain()方法

public static ActivityThread systemMain() {
    ...
    ActivityThread thread = new ActivityThread();
    thread.attach(true, 0);
    return thread;
}

在ActivityThread的systemMain()方法中调用了attach()方法

private void attach(boolean system, long startSeq) {
    ...
	if (!system) {
            ...
        } else {
           ...
            try {
                mInstrumentation = new Instrumentation();
                mInstrumentation.basicInit(this);
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo); // 1.创建ContextImpl
                // 创建Application
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }
    ...
}

需要注意的是,在attch()方法中有一个system的标志来区分system_server进程和应用进程。在systemMain()方法中调用attach()方法时system为true。所以我们直接看这个逻辑分支里的代码。

在开始创建Application前还有些准备工作:

  • 创建了Instrumentation对象,用于之后的Application创建;
  • 创建了SystemContext,在创建SystemContext时创建了LoadApk对象;
  • 创建一个ContextImpl用来创建Application;
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
            String opPackageName) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
                null, opPackageName);
        context.setResources(packageInfo.getResources());
        return context;
    }

ContextImpl的createAppContex()方法用来生成一个ContextImpl实例,并且传递了ActivityThread、LoadedApk、opPackageName等参数。

public ContextImpl getSystemContext() {
        synchronized (this) {
            if (mSystemContext == null) {
                mSystemContext = ContextImpl.createSystemContext(this);
            }
            return mSystemContext;
        }
    }
static ContextImpl createSystemContext(ActivityThread mainThread) {
        LoadedApk packageInfo = new LoadedApk(mainThread);
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
                null, null);
        context.setResources(packageInfo.getResources());
        context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                context.mResourcesManager.getDisplayMetrics());
        return context;
    }

创建SystemContext的过程中创建了LoadedApk实例。其中LoadedApk是与Application一一对应的。

接下开始了Application的创建过程,从LoadedApk的makeApplication()方法开始。

LoadedApk的makeApplication()方法

public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

        Application app = null;

        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        "initializeJavaContextClassLoader");
                initializeJavaContextClassLoader();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + ": " + e.toString(), e);
            }
        }
        ...
        return app;
    }

在开始创建Application的过程中LoadedApk的主要工作是先创建了一个ClassLoader用于接下来的创建流程,然后创建流程有来到了Instrumentation中。

Instrumentation的newApplication()

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;
    }

在这里通过反射创建了Application实例。

至此,在system_server中的创建过程就已结束。

应用进程中的创建过程

应用进程是从ActivityThread中的main()方法开始的

public static void main(String[] args) {
    ...
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    ...
}

在这里可以看到依然调用了attach()方法,不同的是system表示是false。接下来就分析下另外一个逻辑分支。

attach()方法的另外一种逻辑

private void attach(boolean system, long startSeq) {
    ...
    if (!system) {
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            ...
        } else {}
    ...
}

在这里我们看到流程进入了AMS中attachApplication()

AMS中的创建过程

如果继续跟代码,就可以发现在attachApplicationLocked()方法中有调用了ActivityThread的bindApplication。这个过程是通过Binder方式进行通信的。

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
    ...
    thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions);
    ..
}

ActivityThread的bindApplication()

public final void bindApplication(...) {
     ...
     sendMessage(H.BIND_APPLICATION, data);
     ...
}

在这里通过Handler发送BIND_APPLICATION的消息完成了Application的创建。

private void handleBindApplication(AppBindData data) {
    mBoundApplication = data;
    Process.setArgV0(data.processName);//
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    ...

    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    ...

    try {
        // 此处data.info是指LoadedApk, 通过反射创建目标应用Application对象
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;
        ...
        mInstrumentation.onCreate(data.instrumentationArgs);
        mInstrumentation.callApplicationOnCreate(app);

    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

在handleBindApplication()方法中创建Application的过程就跟system_server进程中创建的过程大同小异了。

总结

应用进程的Application创建过程,跟system进程的核心逻辑都差不多。只是app进程多了两次binder调用。