Skip to content

ActivityThread.main

追踪 ActivityThread.main 的进程环境、startSeq/deli queue、MainLooper、attachApplication 和 GC watcher。

基于android-17.0.0_r1
AndroidActivityThreadAMSLooper源码阅读

ActivityThread.main ​

ActivityThread.main() 是普通 Android 应用 Java 主线程的入口,但它不会直接创建 Application。它先安装进程级 syscall forwarding、用户目录、证书目录和 mainline module,解析 startSeq/deli queue,创建 MainLooper,再构造 ActivityThread 并通过 attachApplication(mAppThread, startSeq) 向 AMS 报到。Application、ContentProvider 和组件生命周期由 AMS 回调后的 handleBindApplication() 才建立。

1. 进程环境 ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

java
public static void main(String[] args) {
    Trace.traceBegin(
            Trace.TRACE_TAG_ACTIVITY_MANAGER,
            "ActivityThreadMain");

    AndroidForwardingOs.install();
    CloseGuard.setEnabled(false);
    Environment.initForCurrentUser();

    File configDir = Environment
            .getUserConfigDirectory(UserHandle.myUserId());
    TrustedCertificateStore
            .setDefaultUserDirectory(configDir);

    initializeMainlineModules();
    Process.setArgV0("<pre-initialized>");

forwarding OS、CloseGuard、user environment、证书目录和 mainline service managers 都在应用代码执行前设置。进程名暂时改成 <pre-initialized>,真正包名/进程名在 bind application 阶段更新。

2. startSeq关联 ​

java
long startSeq = 0;
if (args != null) {
    for (int i = args.length - 1; i >= 0; --i) {
        if (args[i].startsWith(PROC_START_SEQ_IDENT)) {
            startSeq = Long.parseLong(
                    args[i].substring(
                        PROC_START_SEQ_IDENT.length()));
        }
    }
}

seq=<number> 由 ProcessList 添加,经 Zygote wire protocol 和 RuntimeInit 原样传到 ActivityThread。AMS 用它把 attach 与当前 ProcessRecord 启动请求匹配,避免旧进程迟到的 attach 占用新启动记录。

3. DeliQueue时机 ​

java
if (args[i].startsWith("--use-deliqueue=")) {
    boolean useDeliQueue = Boolean.parseBoolean(
            args[i].substring(
                args[i].indexOf('=') + 1));
    MessageQueue.setUseDeliQueue(useDeliQueue);
}

Looper.prepareMainLooper();

deli queue 必须在 prepareMainLooper() 之前设置,因为后者会创建 MessageQueue。该参数来自 platform compat;放错参数顺序或在 Looper 后设置都不会改变已经创建的主队列。

4. 主线程对象 ​

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

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

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException(
        "Main thread loop unexpectedly exited");

ActivityThread 不是 Thread 子类,而是应用主线程状态/消息分发 owner;真正线程就是执行 main 的 Zygote 子进程主线程。mH/main handler 消费 bind application、launch activity、service、receiver、configuration 等消息。Looper.loop() 是正常终点,返回即致命错误。

5. 应用attach ​

源码文件:frameworks/base/core/java/android/app/ActivityThread.java

java
private void attach(boolean system, long startSeq) {
    sCurrentActivityThread = this;
    mConfigurationController =
            new ConfigurationController(this);
    mSystemThread = system;
    mStartSeq = startSeq;
    mDdmSyncStageUpdater.next(Stage.Attach);

    if (!system) {
        DdmHandleAppName.setAppName(
                "<pre-initialized>",
                UserHandle.myUserId());
        RuntimeInit.setApplicationObject(
                mAppThread.asBinder());
        IActivityManager mgr =
                ActivityManager.getService();
        mgr.attachApplication(mAppThread, startSeq);
        ...
    }
}

attach 首先发布进程内 current ActivityThread、配置控制器和 startSeq;mAppThread 是 ApplicationThread Binder stub,AMS 后续通过它回调应用。RuntimeInit.setApplicationObject() 让 crash handler 可以向 AMS 报告当前应用 Binder。

6. GC watcher ​

java
BinderInternal.addGcWatcher(() -> {
    if (!mSomeActivitiesChanged) return;
    Runtime runtime = Runtime.getRuntime();
    long max = runtime.maxMemory();
    long used = runtime.totalMemory()
            - runtime.freeMemory();
    if (used > (3 * max) / 4) {
        mSomeActivitiesChanged = false;
        ActivityTaskManager.getService()
                .releaseSomeActivities(mAppThread);
    }
});

GC 后若 activity 状态变化且 Java heap 使用超过 3/4,应用请求 ATM 释放部分 Activity。这个 watcher 不负责触发 GC,也不直接 kill 进程;它是高内存压力下的组件回收消费者。

7. 配置回调 ​

java
ViewRootImpl.addConfigCallback(
        globalConfig -> {
            synchronized (mResourcesManager) {
                if (mResourcesManager
                        .applyConfigurationToResources(
                            globalConfig, null)) {
                    Configuration updated =
                            mConfigurationController
                                    .updatePendingConfiguration(
                                        globalConfig);
                    if (updated != null) {
                        sendMessage(
                                H.CONFIGURATION_CHANGED,
                                globalConfig);
                    }
                }
            }
        });

attach 后注册 ViewRootImpl config callback,先在 ResourcesManager 锁内更新资源,再通过 ActivityThread Handler 投递 configuration changed。资源更新和组件回调分两个阶段,避免 View 层看到旧 Resources。

8. 状态与失败边界 ​

  • ActivityThread 对象已创建:不代表 Application 已创建;
  • attachApplication 已发送:不代表 AMS 已回调 bind application;
  • main Handler 已保存:消息队列已存在,但可能尚无组件;
  • RemoteException:system_server 异常,应用 attach 失败并退出;
  • startSeq 不匹配:AMS 清理迟到/过期进程;
  • Looper 退出:主线程致命状态;
  • GC watcher 失败:高内存 Activity 回收链中断,不等于 attach 失败。

9. 导航与后续 ​

bash
# 主入口、环境、参数、Looper 和 attach。
rg -n "public static void main|AndroidForwardingOs|initForCurrentUser|PROC_START_SEQ_IDENT|use-deliqueue|prepareMainLooper|attach\(false|Looper.loop" \
  frameworks/base/core/java/android/app/ActivityThread.java

# attach 状态、ApplicationThread Binder、GC watcher 和配置回调。
rg -n "private void attach|setApplicationObject|attachApplication|addGcWatcher|releaseSomeActivities|addConfigCallback|CONFIGURATION_CHANGED" \
  frameworks/base/core/java/android/app/ActivityThread.java

下一篇将进入 AMS 回调后的 handleBindApplication(),解释 LoadedApk、Instrumentation、ContentProvider、Application 创建和 onCreate 顺序;不会重复主 Looper 和 attach 请求。