Application创建流程分析

前言

要想启动一个应用程序,首先要保证这个应用程所需要的应用程序进程已经创建启动。AMS在启动应用程序时,会检查这个应用程序需要的应用程序进程是否存在,不存在就会请求Zygote孵化器进程来启动需要的应用程序进程。因此应用程序进程启动过程可以概括为两个部分:

  • AMS发送启动应用程序进程请求
  • Zygote接收请求并创建应用程序进程

关于这部分的具体流程分析可参考《Android进阶解密》第二章内容。本文重点分析Zygote创建应用程序进程走到ActivityThread的main方法后,创建Application的流程。

进入ActivityThread的main方法,需要关注的核心代码如下:

frameworks/base/core/java/android/app/ActivityThread.java

public static void main(String[] args) {
    ...

    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    // 需要关注的代码
    thread.attach(false);
    ...
    Looper.loop();
	...
}

接下来进入attach方法,代码很多,但是需要重点关注的就这几行:

private void attach(boolean system) {
    ...
    // 注释1
    final IActivityManager mgr = ActivityManager.getService();
    try {
        // 注释2
        mgr.attachApplication(mAppThread);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
	...
}

如果对Binder机制稍有了解,你就会知道,注释1处调用ActivityManager的getService方法来获取AMS的代理对象,接着调用AMS的attachApplication方法。这里与Android8.0之前的代码逻辑有些不同,Android8.0之前是通过ActivityManagerNative的getDefault来获取AMS的代理对象的,现在这个逻辑封装到了ActivityManager中而不是ActivityManagerNative中。这里先查看ActivityManager的getService方法:

public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() {
            @Override
            protected IActivityManager create() {
                // 注释1
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                // 注释2
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };

在注释1处获取IBinder类型的AMS引用(binder对象),接着在注释2处将它转换成IActivityManager类型的对象(也就是AMS的代理对象),这段代码采用的AIDL,IActivityManager.java文件是由AIDL工具在编译时自动生成的,IActivityManager.aidl的文件路径为frameworks/base/core/java\android/app/IActivityMananger.aidl。要实现跨进程通信,服务端也就是AMS只需要继承IActivityManager.Stub类并实现相应的方法就可以了。Android8.0之前并没有采用AIDL,用AMS的代理对象ActivityManagerProxy来与AMS进行通信,Android8.0去除了ActivityManagerNative的内部类ActivityManagerProxy,代替它的是IActivityManager,它是AMS在本地的代理。言归正传,回到attach方法,接下来进入AMS的attachApplication方法(跨进程通信,AMS在SystemServer进程)

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        // 注释1
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}

接下来进入注释1处的attachApplicationLocked方法:

private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid) {

    // Find the application record that is being attached...  either via
    // the pid if we are running in multiple processes, or just pull the
    // next app record if we are emulating process with anonymous threads.
    // 用于描述一个应用程序进程(记录应用程序进程的相关信息)
    ProcessRecord app;
    ...
        if (app.instr != null) {
            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 {
            thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                    null, null, null, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(getGlobalConfiguration()), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial);
        }
    ...

    return true;
}

AMS负责四大组件的启动、切换、调度以及应用程序进程的管理,是Android中最为核心的服务,参与了应用程序的启动管理。这里省去了大量的检查和初始化的代码,保存要创建应用程序进程的相关信息等操作,也就是说通过ProcessRecord即应用程序进程信息的相关判断,thread是IApplicationThread类型的,此处代表的是IApplicationThread的代理对象,调用bindApplication方法,ApplicationThread继承IApplicationThread.Stub,此处又是Binder机制的跨进程通信,接下来进入ApplicationThread的bindApplication方法,ApplicationThread是ActivityThread的内部类,又从AMS所在的SystemServer系统服务进程回到了应用程序进程。

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

    if (services != null) {
        // Setup the service cache in the ServiceManager
        ServiceManager.initServiceCache(services);
    }

    setCoreSettings(coreSettings);

    AppBindData data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providers;
    ......
    // 注释1
    sendMessage(H.BIND_APPLICATION, data);
}

将应用程序进程的相关信息保存到AppBindData类型的data中,通过sendMessage方法发送消息,交给H类型的Handler处理

private class H extends Handler {
    ...
    public static final int BIND_APPLICATION        = 110;
    ...
    public void handleMessage(Message msg) {
        switch (msg.what) {
            ...
                case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                	//调用ActivityThread的handleBindApplication()方法处理
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
            ...
        }
    }
}

进入H类的handleMessage方法,找到BIND_APPLICATION对应的case,从msg中取出之前保存的AppBindData类型的数据data,交给handleBindApplication方法

 private void handleBindApplication(AppBindData data) {
   // 注释1 获取LoadedApk
   data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
   ...
   try {
       // 注释2
       // 创建一个Application对象     
       Application app = data.info.makeApplication(data.restrictedBackupMode,null);
       mInitialApplication = app;
       try {
          // 注释3
          // 通过mInstrumentation对象,回调Application的onCreate()方法  
           mInstrumentation.callApplicationOnCreate(app);
       } catch (Exception e) {
            ...
        } finally {
            ...
        }
        ...  
}

先看注释1处,通过getPackageInfoNoCheck()方法对AppBindData对象的info变量赋值,info变量的类型是LoadedApk,关于LoadedApk,有一个通俗的说法,LoadedApk对象是apk文件在内存中的表示,apk文件的相关信息,比如apk文件中的资源,甚至是代码里面的Activity、Service等组件的信息都可以通过此对象获取,我们来看下getPackageInfoNoCheck()方法的源码

public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
            CompatibilityInfo compatInfo) {
    return getPackageInfo(ai, compatInfo, null, false, true, false);
}

接着进入getPackageInfo方法:

private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
        ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
        boolean registerPackage) {
        /*
         * 下面这个地方不是很理解,看下面这一行代码的意思应该是判断是不是同一个用户
         * 查了一下,differentUser的值大部分情况下应该都是false
         */
        final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
        synchronized (mResourcesManager) {
            WeakReference<LoadedApk> ref;
            if (differentUser) {
                // Caching not supported across users
                ref = null;
            } else if (includeCode) {
                /*在getPackageInfoNoCheck()方法中调用本方法时,includeCode的值为true
                 *从缓存中根据应用的报名获取LoadedApk的弱引用对象
                 */
                ref = mPackages.get(aInfo.packageName);
            } else {
                ref = mResourcePackages.get(aInfo.packageName);
            }
 
            LoadedApk packageInfo = ref != null ? ref.get() : null;
            /*
             * 当获取的LoadedApk对象为null时,或者说是放缓存中不存在对应的LoadedApk对象时候
             * 则调用LoadedApk的构造方法,创建一个LoadedApk对象
             */
            if (packageInfo == null || (packageInfo.mResources != null
                    && !packageInfo.mResources.getAssets().isUpToDate())) {            
                ...
               
                packageInfo =
                    new LoadedApk(this, aInfo, compatInfo, baseLoader,
                            securityViolation, includeCode &&
                            (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
 
                ...
                
                if (differentUser) {
                    // Caching not supported across users
                } else if (includeCode) {
                    //把创建的LoadedApk对象放入缓存中
                    mPackages.put(aInfo.packageName,
                            new WeakReference<LoadedApk>(packageInfo));
                } else {
                    mResourcePackages.put(aInfo.packageName,
                            new WeakReference<LoadedApk>(packageInfo));
                }
            }
            return packageInfo;
        }
}

总结一下getPackageInfo()方法的作用就是,从缓存中获取对应的LoadedApk对象,若缓存中不存在该对象,便去创建一个对象,保存在缓存里,并return LoadedApk的对象,最终把该对象赋值给handleBindApplication()中的data.info。

我们继续回到handleBindApplication()方法中的注释2处,调用data.info也就是LoadedApk对象的makeApplication()方法,创建一个Application对象,我们来看下makeApplication()方法

frameworks/base/core/java/android/app/LoadedApk.java

public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        
        //若Application已经创建过,直接return
        if (mApplication != null) {
            return mApplication;
        }
        ...
        Application app = null;
        ...
        try {
            ...
            // 注释1
            // 获取一个ContextImpl上下文对象
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            
            // 注释2             
            // 通过Instrumentation对象的newApplication()方法创建一个Application对象,
            // 创建的这个Application对象也是makeApplication()方法最终return的对象
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            ...
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
        ...
        return app;
}

注释1处,内部主要还是通过new ContextImpl(xxx)的形式创建ContextImpl对象。再看注释2处,进入Instrumentation的newApplication方法,顾名思义它的作用就是创建Application

static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
	Application app = (Application)clazz.newInstance();
    app.attach(context);
    return app;
}

该反方最终通过反射的方式创建了一个Application对象,并且调用了Appliction的attach()方法,而attach方法又调用了attachBaseContext方法,现在应该明白为什么该方法在Application的onCreate之前调用了。

final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

接下来回到handleBindApplication方法的注释3处,通过mInstrumentation对象,调用callApplicationOnCreate方法,顾名思义就是去调用执行Application的onCreate()方法

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

文章的后半部分主要是从handleBindApplication方法的3处重要逻辑展开的,为了看得更清晰一点,简单小结一下:

  • data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); 获取保存Apk文件信息的LoadedApk对象
  • Application app = data.info.makeApplication(data.restrictedBackupMode,null); 内部通过反射创建Application对象,在这个过程中会调用Application的attachBaseContext方法
  • mInstrumentation.callApplicationOnCreate(app); 通过Instrumentation的callApplicationOnCreate方法执行Application的生命周期方法onCreate
原创文章 23 获赞 30 访问量 9558

猜你喜欢

转载自blog.csdn.net/my_csdnboke/article/details/106145205