App進程的Application創建、啓動過程源碼解析(Android P)

在用戶手機上,一個App的啓動通常是由用戶點擊Launcher上的圖標來啓動的。App啓動時的起點在哪裏?Application對象又是如何創建的呢?

接下來我們通過Android P的源碼來分析具體實現過程,解開我們的疑問。

進程的啓動過程及Application對象的創建過程分析

一個App系統發起啓動命令,一直到啓動起來,它的第一步就是要啓動一個App所對應的進程,該進程承載了我們將要運行的業務。

ActivityThread的main()方法和attach()方法

ActivityThread在我們的Android系統中,是一個非常重要的類,它同時也代表了我們App運行所對應的主線程。那麼一個進程啓動,就是從ActivityThread類的main函數開始的。

代碼位置:/frameworks/base/core/java/android/app/ActivityThread.java

入口函數main

ActivityThread在App啓動及運行過程中一個非常重要的類。ActivityThread的main方法是App的入口方法,ActivityThread代表了App的主線程或UI線程。

    public static void main(String[] args) {
        ……
        Process.setArgV0("<pre-initialized>"); //設置進程參數

        Looper.prepareMainLooper();

        ……
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        ……
        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

主要進行了以下幾個操作:

  1. 初始化MainLooper。
  2. 創建ActivityThread實例對象,並調用attach實例方法。
  3. 初始化主線程的Handler,並賦值給sMainThreadHandler屬性。
  4. 主進程進入Looper循環。

main方法執行過後,App所在進程就擁有了一個具有MainLooper,並且已經進入Looper循環監聽的這麼一個主線程了。ActivityThread對象也進行了相應的創建和初始化設置,主線程的Handler也進行了初始化工作,隨時都準備接受消息,進行消息處理的工作了。

ActivityThread的構造函數

ActivityThread構造方法調用時,會初始化ResourcesManager對象。

    ActivityThread() {
        mResourcesManager = ResourcesManager.getInstance();
    }

ActivityThread的attach方法

ActivityThread的attach方法:

    private void attach(boolean system, long startSeq) {
        sCurrentActivityThread = this;
        mSystemThread = system; //是否是系統進程,我們的App這個值是false
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());//ApplicationThread的binder對象,用於通信
            final IActivityManager mgr = ActivityManager.getService();//獲取AMS服務
            try {
                mgr.attachApplication(mAppThread, startSeq);//遠程調用AMS服務的attachApplication來啓動一個Application
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            // Watch for getting close to heap limit. 註冊GC檢測器,當可用內存較低時,清理隱藏Activity
            BinderInternal.addGcWatcher(new Runnable() {
                @Override public void run() {
                    if (!mSomeActivitiesChanged) {
                        return;
                    }
                    Runtime runtime = Runtime.getRuntime();
                    long dalvikMax = runtime.maxMemory();
                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                    if (dalvikUsed > ((3*dalvikMax)/4)) {
                        if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                + " total=" + (runtime.totalMemory()/1024)
                                + " used=" + (dalvikUsed/1024));
                        mSomeActivitiesChanged = false;
                        try {
                            mgr.releaseSomeActivities(mAppThread); //執行隱藏Activity棧的內存清理
                        } catch (RemoteException e) {
                            throw e.rethrowFromSystemServer();
                        }
                    }
                }
            });
        } else {
            // Don't set application object here -- if the system crashes,
            // we can't display an alert, we just want to die die die.
            android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());
            try {
                mInstrumentation = new Instrumentation();
                mInstrumentation.basicInit(this);
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }

        // add dropbox logging to libcore
        DropBox.setReporter(new DropBoxReporter());

        ViewRootImpl.ConfigChangedCallback configChangedCallback
                = (Configuration globalConfig) -> {
            synchronized (mResourcesManager) {
                // We need to apply this change to the resources immediately, because upon returning
                // the view hierarchy will be informed about it.
                if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
                        null /* compat */)) {
                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                            mResourcesManager.getConfiguration().getLocales());

                    // This actually changed the resources! Tell everyone about it.
                    if (mPendingConfiguration == null
                            || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
                        mPendingConfiguration = globalConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                    }
                }
            }
        };
        ViewRootImpl.addConfigCallback(configChangedCallback);
    }
參數:

system:是否是系統進程。
startSeq:通過命令行傳遞過來的值(PROC_START_SEQ_IDENT),默認值爲0。

邏輯解析:
  1. 首先檢測該進程釋放是系統進程,在這裏我們重點來看非系統進程。
  2. RuntimeInit.setApplicationObject傳遞ApplicationThread的binder對象,爲進程通信做準備。
  3. 遠程調用AMS服務的attachApplication來啓動一個Application,我們後面重點來分析。
  4. 註冊GC檢測器,當可用內存較低時,清理隱藏Activity。
  5. ViewRootImpl.ConfigChangedCallback註冊配置改變的監聽。

清理隱藏Activity棧

我們首先來看下上面的第4點,註冊GC檢測器,當可用內存較低時,清理隱藏Activity。

我們來分析它的技術實現。

BinderInternal.addGcWatcher註冊一個GC監聽器,用於在內存使用率達到一定比例時,啓動隱藏Activity棧的清理工作,以釋放更多內存。

我們來看這個GC監聽器是如何註冊生效的?

1. BinderInternal實現

/frameworks/base/core/java/com/android/internal/os/BinderInternal.java

    static WeakReference<GcWatcher> sGcWatcher
            = new WeakReference<GcWatcher>(new GcWatcher());
    static ArrayList<Runnable> sGcWatchers = new ArrayList<>();
    static Runnable[] sTmpWatchers = new Runnable[1];
    static long sLastGcTime;
    static final BinderProxyLimitListenerDelegate sBinderProxyLimitListenerDelegate =
            new BinderProxyLimitListenerDelegate();

    static final class GcWatcher {
        @Override
        protected void finalize() throws Throwable {
            handleGc();
            sLastGcTime = SystemClock.uptimeMillis();
            synchronized (sGcWatchers) {
                sTmpWatchers = sGcWatchers.toArray(sTmpWatchers);
            }
            for (int i=0; i<sTmpWatchers.length; i++) {
                if (sTmpWatchers[i] != null) {
                    sTmpWatchers[i].run();
                }
            }
            sGcWatcher = new WeakReference<GcWatcher>(new GcWatcher());
        }
    }

    public static void addGcWatcher(Runnable watcher) {
        synchronized (sGcWatchers) {
            sGcWatchers.add(watcher);
        }
    }

邏輯解析:

它的原理是利用了finalize()方法來實現的。具體如下:

  1. 首先註冊一個弱引用的GcWatcher對象,當GC回首弱引用時,就會觸發它的finalize()方法;
  2. sTmpWatchers數組中存放了需要處理的註冊監聽,它是一個Runnable數組;
  3. 在finalize()方法中,我們遍歷sTmpWatchers數組,調用Runnable對象的run()方法執行監聽事件;
  4. 執行完畢通知事件之後,之前的GcWatcher對象已經作爲垃圾回收掉了,我們需要重新生成一個作爲下一次GC的監聽入口。

執行隱藏Activity內存清理的條件是dalvikUsed > ((3*dalvikMax)/4),也即是當前已使用內存大於總內存的3/4時,滿足執行條件。

執行清理的工作是由AMS的releaseSomeActivities方法來進行的。

2. releaseSomeActivities方法

ActivityManagerService的releaseSomeActivities方法:

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

    @Override
    public void releaseSomeActivities(IApplicationThread appInt) {
        synchronized(this) {
            final long origId = Binder.clearCallingIdentity();
            try {
                ProcessRecord app = getRecordForAppLocked(appInt); //從最近運行App列表中找到對應的ProcessRecord對象
                mStackSupervisor.releaseSomeActivitiesLocked(app, "low-mem"); //執行隱藏Activity棧的清理工作
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    }

這裏調用了ActivityStackSupervisor的實例方法releaseSomeActivitiesLocked來進行Activity工作棧的操作。

代碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

回收規則:
  1. 對於單棧(TaskRecord)應用,在前臺的時候,所有界面都不會被回收,只有多棧情況下,系統纔會回收不可見棧的Activity。
  2. ActivityStack利用maxTasks 保證,最多清理tasks.size() / 4,最少清理1個TaskRecord。

ActivityManagerService的attachApplication()方法

ActivityManagerService的attachApplication()方法是進程Application創建的核心邏輯,我們來分析它的實現過程。

ActivityThread的attach方法,遠程調用AMS服務的attachApplication來啓動一個Application,這裏的參數爲ApplicationThread的實例,ApplicationThread類是ActivityThread的內部類,負責與AMS等服務進行Binder通信。

    @Override
    public final void attachApplication(IApplicationThread thread, long startSeq) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            Binder.restoreCallingIdentity(origId);
        }
    }

這裏調用了attachApplicationLocked方法:

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

        // 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;
        ……
        //獲取進程所對應的ProcessRecord對象。
        if (app == null) {
            ……
            //獲取失敗,退出進程
            return false;
        }

        // If this application record is still attached to a previous
        // process, clean it up now.
        if (app.thread != null) {//如果該ProcessRecord對象之前attached到了一個進程,則進行清理操作
            handleAppDiedLocked(app, true, true);
        }
        ……
        final String processName = app.processName;
        ……
        //註冊Binder死亡監聽
        ……
        //以下進行ProcessRecord對象的相關初始化操作
        app.makeActive(thread, mProcessStats);//綁定ApplicationThread對象
        app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;//進程優先級設置
        app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
        app.forcingToImportant = null;
        updateProcessForegroundLocked(app, false, false);//前臺服務相關設置
        app.hasShownUi = false;
        app.debugging = false;
        app.cached = false;
        app.killedByAm = false;
        app.killed = false;


        // We carefully use the same state that PackageManager uses for
        // filtering, since we use this flag to decide if we need to install
        // providers when user is unlocked later
        app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);

        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

        ……
        provider相關處理
        ……
        ……
        try {
            ……
            ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info;
            app.compat = compatibilityInfoForPackageLocked(appInfo);

            ……

            //Build.SERIAL獲取,Android P以下可以獲取到

            ……
            //Instrumentation處理,多進程的使用同一個Instrumentation(後續進程併入第一個進程)。

            ……
            if (app.isolatedEntryPoint != null) {
                // This is an isolated process which should just call an entry point instead of
                // being bound to an application.
                thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
            } else if (app.instr != null) {//Instrumentation不爲空
                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, isAutofillCompatEnabled);
            } 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, isAutofillCompatEnabled);
            }
            ……
            checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
            updateLruProcessLocked(app, false, null);
            checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
            app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
        } catch (Exception e) {
            ……
            return false;
        }

        // 從正在啓動進程列表刪除
        mPersistentStartingProcesses.remove(app);
        ……
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {//查看頂部可展示Activity是否正在等待在當前進程中運行。也就是處理Activity展示
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }

        // Find any services that should be running in this process...
        if (!badApp) {
            try {
                didSomething |= mServices.attachApplicationLocked(app, processName); //處理需要運行在當前進程中的Service
                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            }
        }

        // Check if a next-broadcast receiver is in this process...
        //處理需要運行在當前進程中的broadcast receiver
        if (!badApp && isPendingBroadcastProcessLocked(pid)) {
            try {
                didSomething |= sendPendingBroadcastsLocked(app);
                checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");
            } catch (Exception e) {
                // If the app died trying to launch the receiver we declare it 'bad'
                Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
                badApp = true;
            }
        }

        ……

        if (!didSomething) {
            updateOomAdjLocked();
            checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
        }

        return true;
    }      
            
邏輯解析:
  1. 獲取進程所對應的ProcessRecord對象。
  2. 註冊Binder死亡監聽
  3. 進行ProcessRecord對象的相關初始化操作
  4. Instrumentation處理,多進程的使用同一個Instrumentation(後續進程併入第一個進程)。
  5. 調用thread.bindApplication真正啓動Application。這裏是Application的啓動過程。
  6. 處理Activity顯示、Service、BroadcastReceiver等。這裏涉及到Activity的啓動過程,我們後面來分析。

調用mStackSupervisor.attachApplicationLocked(app)啓動Activity棧中,需要展示的Activity頁面。

這裏的thread.bindApplication方法調用,是真正創建Application對象的地方,我們重點來看。

Application的啓動

在ActivityManagerService中的attachApplicationLocked方法在服務AMS進程中,遠程調用當前進程的ApplicationThread的bindApplication來創建並啓動App所對應的的Application。

ApplicationThread繼承自IApplicationThread.Stub,這裏也證明了它的重要功能就是實現AMS與Client進行間進行Binder通信使用。

ApplicationThread的bindApplication方法

bindApplication方法:
/frameworks/base/core/java/android/app/ActivityThread.java

        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, boolean autofillCompatibilityEnabled) {

            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;
            data.instrumentationName = instrumentationName;
            data.instrumentationArgs = instrumentationArgs;
            data.instrumentationWatcher = instrumentationWatcher;
            data.instrumentationUiAutomationConnection = instrumentationUiConnection;
            data.debugMode = debugMode;
            data.enableBinderTracking = enableBinderTracking;
            data.trackAllocation = trackAllocation;
            data.restrictedBackupMode = isRestrictedBackupMode;
            data.persistent = persistent;
            data.config = config;
            data.compatInfo = compatInfo;
            data.initProfilerInfo = profilerInfo;
            data.buildSerial = buildSerial;
            data.autofillCompatibilityEnabled = autofillCompatibilityEnabled;
            sendMessage(H.BIND_APPLICATION, data);
        }
邏輯解析:
  • services保存了基礎的一些系統Service服務,這裏調用ServiceManager的initServiceCache方法,將這些Serivce服務添加到SM中的緩存列表"sCache"中。
  • 生成AppBindData對象,並設置Application的初始化信息。
  • 發送BIND_APPLICATION消息,繼續處理。

ActivityThread的handleBindApplication方法

H的handleMessage對BIND_APPLICATION消息進行處理:

        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    
        }

這裏直接調用handleBindApplication方法進行Application的正式啓動過程。

handleBindApplication:

    private void handleBindApplication(AppBindData data) {
        ……

        mBoundApplication = data;//mBoundApplication賦值
        ……
        Process.setArgV0(data.processName);//設置進程名稱
        android.ddm.DdmHandleAppName.setAppName(data.processName,
                                                UserHandle.myUserId());
        VMRuntime.setProcessPackageName(data.appInfo.packageName);//設置相關包名

        ……
        //解碼Bitmap使用的規則,Android P之前使用BitmapFactory,之後使用ImageDecoder
        ImageDecoder.sApiLevel = data.appInfo.targetSdkVersion;

        //重置系統時區
        TimeZone.setDefault(null);
        ……

        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);//生成LoadedApk對象

        ……

        // 設置Build的SERIAL屬性值
        try {
            Field field = Build.class.getDeclaredField("SERIAL");
            field.setAccessible(true);
            field.set(Build.class, data.buildSerial);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            /* ignore */
        }

        ……
        //debug相關設置
        ……
        //設置Instrumentation
        ……
        //創建appContext對象
        ……
        if (ii != null) {
            ……
            //創建Instrumentation對象,並執行init初始化
            final ComponentName component = new ComponentName(ii.packageName, ii.name);
            mInstrumentation.init(this, instrContext, appContext, component,
                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection);

            ……
        } else {
            mInstrumentation = new Instrumentation();
            mInstrumentation.basicInit(this);
        }

        ……
        // 在進程啓動過程中或Provider安裝過程中,暫時允許訪問磁盤權限
        Application app;
        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
        try {
            // 創建Application對象
            app = data.info.makeApplication(data.restrictedBackupMode, null);
            ……
            mInitialApplication = app;

            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode) {//如果應用正在安裝或恢復這類特殊狀態,restrictedBackupMode值爲true。這裏正常情況下爲false
                if (!ArrayUtils.isEmpty(data.providers)) {
                    installContentProviders(app, data.providers); //此處安裝ContentProvider
                    // For process that contains content providers, we want to
                    // ensure that the JIT is enabled "at some point".
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }

            // 在providers安裝之後,執行Instrumentation對象的onCreate方法,啓動Instrumentation線程
            try {
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
            ……
            try {
                mInstrumentation.callApplicationOnCreate(app);//通過callApplicationOnCreate,調用Application對象的onCreate方法
            }
            ……
        } finally {
            ……
        }
        ……
        // 預加載字體資源相關處理
        
    }
邏輯解析

這個方法邏輯非常多,我們來看它主要做了哪些處理:

  1. 設置mBoundApplication = data(參數AppBindData對象)。
  2. Process.setArgV0(data.processName)設置進程名稱。
  3. VMRuntime.setProcessPackageName(data.appInfo.packageName)設置包名。
  4. 設置解碼Bitmap使用的規則。
  5. 重置系統時區。
  6. 生成LoadedApk對象。
  7. 設置Build的SERIAL屬性值。
  8. 設置Instrumentation。
  9. 創建appContext對象。
  10. 創建Instrumentation對象,並初始化。
  11. 在進程啓動過程中或Provider安裝過程中,設置暫時允許訪問磁盤權限標誌。
  12. 創建Application對象。
  13. 安裝ContentProvider。
  14. 在providers安裝之後,執行Instrumentation對象的onCreate方法,啓動Instrumentation線程。
  15. 通過Instrumentation對象的callApplicationOnCreate,調用Application對象的onCreate方法。
  16. 預加載字體資源相關處理。

執行完handleBindApplication方法後,我們的應用程序也就啓動完成了。

創建Application對象該過程非常重要,我們詳細分析。

Application對象的創建

在ActivityThread對象的handleBindApplicaiton方法中,創建了Application對象,代碼:

// 創建Application對象
app = data.info.makeApplication(data.restrictedBackupMode, null);

這裏data是一個AppBindData對象,它的info屬性是一個LoadedApk對象,這樣我們就知道,這裏調用的其實是LoadedApk對象的makeApplicaiton方法。

LoadedApk類的makeApplication方法

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

    public Application makeApplication(boolean forceDefaultAppClass, //如果應用正在安裝或恢復這類特殊狀態,restrictedBackupMode值(這裏是第一個參數)爲true,正常啓動應用,這裏是false。
            Instrumentation instrumentation) { //instrumentation參數這裏傳遞進來的是null
        if (mApplication != null) { //已經存在,直接返回
            return mApplication;
        }
        ……
        Application app = null;
        //設置正在啓動的App的Application的類名
        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            //創建並處理ClassLoader對象
            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對象作爲application的Context環境
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            //這裏調用Instrumentation對象的newApplication方法來創建Application對象。
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app); //ContextImpl對象綁定Application對象
        } 
        ……
        mActivityThread.mAllApplications.add(app); //添加到mAllApplications列表
        mApplication = app;

        if (instrumentation != null) { //這裏在App啓動過程中傳遞進來的是null,不會走此邏輯
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!instrumentation.onException(app, e)) {
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
        }
        ……
        // Rewrite the R 'constants' for all library apks.
        ……

        return app;
    }
邏輯解析:
  1. 如果mApplication已經賦值,則直接返回,否則繼續。
  2. 設置正在啓動的App的Application的類名。
  3. 創建並處理ClassLoader對象。
  4. 創建ContextImpl對象作爲application的Context環境。
  5. 調用Instrumentation對象的newApplication方法來創建Application對象,這裏的Instrumentation對象是通過ActivityThread來獲取的。
  6. ContextImpl對象綁定Application對象。
  7. 添加到mAllApplications列表。

接續來看thread.bindApplication真正啓動Application方法。

Instrumentation類的newApplication方法

Application對象的創建最終是在Instrumentation對象的newApplication方法中通過反射調用創建的。

    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        return newApplication(cl.loadClass(className), context);
    }
    
    static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }
邏輯解析:
  1. 首先通過ClassLoader對象加載Application所對應的類名。
  2. 使用Java反射調用,newInstance一個Application對象。
  3. 最後調用Application對象的attach方法,參數是context。這裏就就是我們熟悉的Application的attach方法了,我們可以在這裏處理一些應用程序啓動時的一些初始化工作。

至此,我們的Application的創建及啓動過程已經分析完成了,詳細你也會對此有一個比較清晰的瞭解。整個過程,涉及到了我們App所在的Client端,也涉及到了ActivityManagerService爲代表的Server端,他們之間的通信過程當然是基於Binder了。ApplicationThread作爲了Server端調用Client端的一個引用,實現了它們之間的相互通信。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章