App进程

创建Application的过程中会涉及的对象创建有:ActivityThread,ContextImpl,LoadedApk,Application,整体调用流程:
Application创建过程 - 图1

1、ActivityThread#main

首先由zygote fork后创建新的app进程,并执行ActivityThread的main方法

  1. public static void main(String[] args) {
  2. ,,,
  3. ActivityThread thread = new ActivityThread();
  4. thread.attach(false);
  5. ,,,
  6. }

2、ActivityThread#attach

private void attach(boolean system) {
        sCurrentActivityThread = this;//保存当前的activityThread
        mSystemThread = system;//是否是系统进程,在此为false
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try {
 //mAppThread是在创建ActivityThread的同时就已经同时创建的内部类实例
//final ApplicationThread mAppThread = new ApplicationThread();
                mgr.attachApplication(mAppThread);///AMS的调用
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
...
}

3、AMS#attachApplication

转到 service 进程

public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();//调用者进程pid
            final long origId = Binder.clearCallingIdentity();
//thread对应ActivityThread的成员变量
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

4、AMS#attachApplicationLocked

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
...
        ProcessRecord app;//当每个进程被创建的时候,都会记录在mPidsSelfLocked中,
// 对每个进程的跟踪缓存,具体可以看AMS中mPidsSelfLocked.put方法
        long startTime = SystemClock.uptimeMillis();
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);
            }
        } else {
            app = null;//如果app为null,后面直接return
        }
...忽略一大堆逻辑
 if (app.instr != null) {//当ProcessRecord中的Instrumention实例为null
//调用app进程中ApplicationThread#bindApplication,binder跨进程操作
                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);
            } else {
                ...
            }
}

5、ActivityThread::ApplicationThread#bindApplication

ApplicationThread是ActivityThread内部类,创建之初即被初始化 实例对象为 mAppThread(此步骤已经发生在app进程)

public final void bindApplication(...) {
            if (services != null) {
                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }
...
     AppBindData data = new AppBindData();//创建appBindData对象,存储app相关的信息
...
     sendMessage(H.BIND_APPLICATION, data);//发送BIND_APPLICATION消息到主线程中处理

H是ActivityThread中内部类,继承Handler,实例为mH,用于处理各种主线程的回调消息

6、ActivityThread::H#handleMessage

handleMessage -> BIND_APPLICATION -> ActivityThread#handleBindApplication

private void handleBindApplication(AppBindData data) {
    mBoundApplication = data;
    Process.setArgV0(data.processName);//设置进程名
    ...
    //1.创建LoadedApk对象
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    ...

    // 2.创建ContextImpl上下文
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    ...
    // 3.创建instrumentation
    ...  
    try {
        // 4.创建应用Application
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;
        ...
        mInstrumentation.onCreate(data.instrumentationArgs);
        //回调onCreate
        mInstrumentation.callApplicationOnCreate(app);

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

6.1、创建 LoadedApk

ActivityThread#getPackageInfoNoCheck -> ActivityThread#getPackageInfo

private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
        ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
        boolean registerPackage) {
...    
synchronized (mResourcesManager) {
        WeakReference<LoadedApk> ref;
       ....
        LoadedApk packageInfo = ref != null ? ref.get() : null;
        if (packageInfo == null || (packageInfo.mResources != null
                && !packageInfo.mResources.getAssets().isUpToDate())) {
            //创建LoadedApk
            packageInfo =
                new LoadedApk(this, aInfo, compatInfo, baseLoader,
                        securityViolation, includeCode &&
                        (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);

            ...
           if (includeCode) {   //每个App的LoadedApk都会存入mPackages
                mPackages.put(aInfo.packageName,
                        new WeakReference<LoadedApk>(packageInfo));
            } else {
                mResourcePackages.put(aInfo.packageName,
                        new WeakReference<LoadedApk>(packageInfo));
            }
        }
        return packageInfo;
    }
}

�创建LoadedApk对象,并将将新创建的LoadedApk加入到mPackages. 也就是说每个app都会创建唯一的LoadedApk对象. 此处aInfo来源于ProcessRecord.info变量, 也就是进程中的第一个app.

6.2、创建ContextImpl

ContextImpl#createAppContext

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
    if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
    ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
            null);
    context.setResources(packageInfo.getResources());
    return context;
}

6.3、创建Instrumentation

通过反射创建

try {
    final ClassLoader cl = instrContext.getClassLoader();
    mInstrumentation = (Instrumentation)
        cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
    throw new RuntimeException(
        "Unable to instantiate instrumentation "
        + data.instrumentationName + ": " + e.toString(), e);
}

....

 mInstrumentation.init(this, instrContext, appContext, component,
                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection)

6.4、创建Application对象

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

        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")) {

            }
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            ...
        }
  1. Instrumentation#newApplication
static public Application newApplication(Class<?> clazz, Context context)
        throws InstantiationException, IllegalAccessException, 
        ClassNotFoundException {
    Application app = (Application)clazz.newInstance();//反射创建
    app.attach(context);
    return app;
}
  1. Application#attach -> ContextWrapper#attachBaseContext
final void attach(Context context) {
    attachBaseContext(context);
    mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

�6.5、Application周期回调

Instrumentation#callApplicationOnCreate

public void callApplicationOnCreate(Application app) {
    app.onCreate();
}