アプリプロセスアプリの作成、起動プロセスのソースコード分析(Android P)

ユーザーの携帯電話では、アプリの起動は通常、ユーザーがランチャーのアイコンをクリックすると開始されます。アプリの開始点はどこですか?Applicationオブジェクトはどのように作成されますか?

次に、Android Pのソースコードを通じて特定の実装プロセスを分析し、疑問を解決します。

プロセス起動プロセスとアプリケーションオブジェクト作成プロセス分析

アプリシステムは、起動するまで起動コマンドを開始します。その最初のステップは、実行するビジネスを実行するアプリに対応するプロセスを開始することです。

ActivityThreadのmain()メソッドとattach()メソッド

ActivityThreadは、Androidシステムで非常に重要なクラスであり、アプリの操作に対応するメインスレッドも表します。次に、ActivityThreadクラスのメイン関数からプロセスが開始されます。

コードの場所:/frameworks/base/core/java/android/app/ActivityThread.java

エントリー機能メイン

ActivityThreadは、アプリの起動時と操作時に非常に重要なクラスです。ActivityThreadのメインメソッドは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インスタンスオブジェクトを作成し、インスタンスのアタッチメソッドを呼び出します。
  3. メインスレッドのハンドラーを初期化し、それをsMainThreadHandler属性に割り当てます。
  4. メインプロセスはルーパーループに入ります。

mainメソッドが実行された後、アプリのプロセスにはMainLooperを持つメインスレッドがあり、リスパーするためにルーパーループに入りました。ActivityThreadオブジェクトも作成され、それに応じて初期化され、メインスレッドのハンドラも初期化され、いつでもメッセージを受け入れてメッセージ処理を実行する準備ができています。

ActivityThreadコンストラクタ

ActivityThreadコンストラクターが呼び出されると、ResourcesManagerオブジェクトが初期化されます。

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

ActivityThreadアタッチメソッド

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のバインダーオブジェクトを渡して、プロセス通信の準備をします。
  3. AMSサービスのattachApplicationをリモートで呼び出してアプリケーションを開始します。後で分析に集中します。
  4. GC検出器を登録し、使用可能なメモリが少なくなったら、非表示のアクティビティをクリーンアップします。
  5. ViewRootImpl.ConfigChangedCallbackは、構成変更の監視を登録します。

非表示のアクティビティスタックをクリーンアップする

最初に上記のポイント4を見て、GC検出器を登録し、使用可能なメモリが少なくなったら、非表示のアクティビティをクリーンアップします。

その技術的な実現を分析してみましょう。

BinderInternal.addGcWatcherは、メモリ使用量が特定の割合に達したときに非表示のアクティビティスタックのクリーンアップを開始するGCリスナーを登録して、メモリを解放します。

このGCリスナーが有効になるように登録されている方法を見てみましょう。

1.バインダー内部実装

/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のモニタリングエントリを再生成する必要があります。

非表示のアクティビティメモリクリーニングを実行するための条件は、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を呼び出して、アクティビティワークスタックの操作を実行します。

コードの場所:フレームワーク/ベース/サービス/コア/ java / com / android /サーバー/ am / ActivityStackSupervisor.java

リサイクルルール:
  1. 単一スタック(TaskRecord)アプリケーションの場合、フォアグラウンドではすべてのインターフェースがリサイクルされず、複数のスタックの場合のみ、システムは非表示のスタックのアクティビティをリサイクルします。
  2. ActivityStackはmaxTasksを使用して、tasks.size()/ 4が最大でクリアされ、少なくとも1つのTaskRecordがクリアされるようにします。

ActivityManagerServiceのattachApplication()メソッド

ActivityManagerServiceのattachApplication()メソッドは、Process Applicationによって作成されるコアロジックです。その実装プロセスを分析してみましょう。

ActivityThreadのattachメソッド。リモートでAMSサービスのattachApplicationを呼び出してアプリケーションを開始します。ここでのパラメーターはApplicationThreadのインスタンスです。ApplicationThreadクラスはActivityThreadの内部クラスで、AMSなどのサービスとのバインダー通信を担当します

    @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. バインダーの死の監視にサインアップ
  3. ProcessRecordオブジェクトに関連する初期化操作を実行する
  4. インストルメンテーション処理。複数のプロセスが同じインストルメンテーションを使用します(後続のプロセスは最初のプロセスにマージされます)。
  5. thread.bindApplicationを呼び出して、実際にアプリケーションを起動します。アプリケーションの起動プロセスです。
  6. アクティビティの表示、サービス、BroadcastReceiverなどを処理します。これにはアクティビティのアクティブ化プロセスが含まれます。後で分析します。

mStackSupervisor.attachApplicationLocked(アプリ)を呼び出して、表示する必要があるアクティビティスタックのアクティビティページを開始します。

ここでのthread.bindApplicationメソッドの呼び出しは、Applicationオブジェクトが実際に作成される場所です。

アプリケーション開始

サービスAMSプロセスのActivityManagerServiceのattachApplicationLockedメソッドは、現在のプロセスのApplicationThreadのbindApplicationをリモートで呼び出して、アプリに対応するアプリケーションを作成して起動します。

ApplicationThreadはIApplicationThread.Stubを継承します。これは、その重要な機能がAMSとクライアント間のバインダー通信を実現することであることも証明します。

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);
        }
論理分析:
  • ここでは、ServiceManagerのinitServiceCacheメソッドが呼び出され、これらのSerivceサービスがSMのキャッシュリスト「sCache」に追加されます。
  • AppBindDataオブジェクトを生成し、アプリケーションの初期化情報を設定します。
  • 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メソッドを直接呼び出して、アプリケーションプロセスを正式に開始します。

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. ビットマップをデコードするためのルールを設定します。
  5. システムのタイムゾーンをリセットします。
  6. LoadedApkオブジェクトを生成します。
  7. BuildのSERIAL属性値を設定します。
  8. 計装を設定します。
  9. appContextオブジェクトを作成します。
  10. Instrumentationオブジェクトを作成して初期化します。
  11. プロセスの起動またはプロバイダーのインストールプロセス中に、一時的にディスクへのアクセスを許可する許可フラグを設定します。
  12. Applicationオブジェクトを作成します。
  13. ContentProviderをインストールします。
  14. プロバイダーがインストールされたら、インストルメンテーションオブジェクトのonCreateメソッドを実行して、インストルメンテーションスレッドを開始します。
  15. InstrumentationオブジェクトのcallApplicationOnCreateを介して、ApplicationオブジェクトのonCreateメソッドを呼び出します。
  16. フォントリソース関連の処理をプリロードします。

handleBindApplicationメソッドを実行すると、アプリケーションが起動します。

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. 起動するアプリのアプリケーションクラス名を設定します。
  3. ClassLoaderオブジェクトを作成して処理します。
  4. アプリケーションのContext環境としてContextImplオブジェクトを作成します。
  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オブジェクトを介して、アプリケーションに対応するクラス名をロードします。
  2. Javaリフレクション呼び出し、newInstance、Applicationオブジェクトを使用します。
  3. 最後に、Applicationオブジェクトのattachメソッドを呼び出します。パラメーターはコンテキストです。これは、使い慣れたアプリケーションのattachメソッドです。アプリケーションの起動時に、初期化作業を処理できます。

この時点で、アプリケーションの作成と起動プロセスが分析されて完了しており、これについても詳細に理解できます。プロセス全体には、アプリが配置されているクライアント側とActivityManagerServiceによって表されるサーバー側が含まれます。これらの間の通信プロセスは、もちろんバインダーに基づいています。ApplicationThreadは、サーバーがクライアントを呼び出すためのリファレンスとして機能し、クライアント間の通信を実現します。

公開された9件のオリジナル記事 ・いい 0 ビュー3226

おすすめ

転載: blog.csdn.net/u011578734/article/details/105654761