ActivityThread的main()方法简读

本文详细剖析了Android中ActivityThread的工作原理,包括主线程初始化过程、关键方法的作用及执行流程。

一、首先,看ActivityThread 的介绍:

 * This manages the execution of the main thread in an
 * application process, scheduling and executing activities,
 * broadcasts, and other operations on it as the activity
 * manager requests.

大概的意思就是说:在应用程序里面管理和执行主线程,调度和执行Activity,广播以及在Activity上的其他业务操作。

二、直接上main()方法。

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

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

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

        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

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

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

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

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

三、一句一句来解读吧。
1、Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
Trace是痕迹,踪迹的意思,是在android.os包下的一个类,主要作用是将跟踪事件写入系统跟踪缓冲区,这些跟踪事件可以用Systrace可视化工具收集和使用。看一下traceBegin()方法,是给代码段写一个跟踪信息。

public static void traceBegin(long traceTag, String methodName) {
        if (isTagEnabled(traceTag)) {
            nativeTraceBegin(traceTag, methodName);
        }
    }

public static boolean isTagEnabled(long traceTag) {
        long tags = sEnabledTags;
        if (tags == TRACE_TAG_NOT_READY) {
            tags = cacheEnabledTags();
        }
        return (tags & traceTag) != 0;
    }

private static native void nativeTraceBegin(long tag, String name);

这里传入了traceTag和methodName,首先就是判断跟踪标签是否启用,如果启用,就调用底层方法,开始跟踪事件。

2、SamplingProfilerIntegration.start();
这个类在com.android.internal.os包下,字面意思翻译就是“抽样分析集成工具”,是集成Dalvik抽样分析器框架。start()是静态方法:

    /**
     * Starts the profiler if profiling is enabled.
     */
    public static void start() {
        if (!enabled) {
            return;
        }
        if (samplingProfiler != null) {
            Log.e(TAG, "SamplingProfilerIntegration already started at " + new Date(startMillis));
            return;
        }

        ThreadGroup group = Thread.currentThread().getThreadGroup();
        SamplingProfiler.ThreadSet threadSet = SamplingProfiler.newThreadGroupThreadSet(group);
        samplingProfiler = new SamplingProfiler(samplingProfilerDepth, threadSet);
        samplingProfiler.start(samplingProfilerMilliseconds);
        startMillis = System.currentTimeMillis();
    }

首先拿到当前线程的线程组group ,threadSet ,然后开启抽样分析。

3、CloseGuard.setEnabled(false);
CloseGuard是dalvik.system包下的一个类。CloseGuard 是一种资源清理机制,资源应该被显式关闭清理。setEnabled()明显就是使其失效,不过会在debug builds的时候重现变得有效。

 * CloseGuard is a mechanism for flagging implicit finalizer cleanup of
 * resources that should have been cleaned up by explicit close
 * methods (aka "explicit termination methods" in Effective Java).

4、Environment.initForCurrentUser();
Environment大家都很熟悉:环境。

public static void initForCurrentUser() {
        final int userId = UserHandle.myUserId();
        sCurrentUser = new UserEnvironment(userId);
    }

首先拿到当前进程的Id,然后初始化一个UserEnvironment实例。

5、EventLogger.setReporter(new EventLoggingReporter());
看源码说明,Set the reporter for event logging in libcore,简单就是说给lib库设置事件打印记者。

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

确保可信证书存储在正确的地方以便于查找CA证书。

7、Process.setArgV0("<pre-initialized>");
Process是管理系统流程的工具。setArgV0()是一个本地方法:

    /**
     * Change this process's argv[0] parameter.  This can be useful to show
     * more descriptive information in things like the 'ps' command.
     * 
     * @param text The new name of this process.
     * 
     * {@hide}
     */
    public static final native void setArgV0(String text);

8、Looper.prepareMainLooper();
终于开始干正事了,这里初始化了主线程。首先是在prepare()里面判断当前线程是否为空,因为Looper只允许有一个主线程。

public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

    public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

9、ActivityThread thread = new ActivityThread();
thread.attach(false);

这里直接实例化了一个ActivityThread 对象,并调用了attach(false)。

private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        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 = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            // Watch for getting close to heap limit.
            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);
                        } 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();
                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.addConfigCallback(new ComponentCallbacks2() {
            @Override
            public void onConfigurationChanged(Configuration newConfig) {
                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(newConfig, null)) {
                        updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                                mResourcesManager.getConfiguration().getLocales());

                        // This actually changed the resources!  Tell
                        // everyone about it.
                        if (mPendingConfiguration == null ||
                                mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                            mPendingConfiguration = newConfig;

                            sendMessage(H.CONFIGURATION_CHANGED, newConfig);
                        }
                    }
                }
            }
            @Override
            public void onLowMemory() {
            }
            @Override
            public void onTrimMemory(int level) {
            }
        });
    }

有耐心的就看看。

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

判断当前主线程的Handler是否为空。

11、if (false) {
Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
}

12、Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
跟前面的Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");相呼应,结束跟踪。

13、Looper.loop();
最重要的一句来了,前面Looper.prepareMainLooper()开启主线程,而这里的loop()就是处理主线程程序的关键段,所有通过Handler传到主线程的Message都会缓存在Looper的消息队列Queue里面,loop()里有个for(;;)循环,不断的从消息队列里面拿出消息进行处理,然后就有了事件的信息交流啦。

14、最后一句throw new RuntimeException("Main thread loop unexpectedly exited");
必要的异常处理语句。

最后说一句,若有任何问题和疑问,欢迎指正。

<think> 我们需要回答两个核心问题: 1. zygote fork新进程成功后为什么会直接调用ActivityThread.main方法? 2. ActivityThread不是线程吗? 首先,理解zygote fork新进程的过程: - 在Android系统中,当需要启动一个新的应用进程时,系统会通过socket向zygote进程发送一个fork请求。 - zygote进程会fork自身,生成一个新的子进程(这就是新应用进程)。 - 然后,在这个新创建的子进程中,会执行一个非常重要的方法ActivityThread.main()。 其次,ActivityThread虽然名字里有Thread,但它并不是一个线程(Thread),而是一个普通的Java类。这个类是每个应用程序进程的主类,它代表了应用程序的主线程(UI线程)的运行环境。 解释为什么fork后直接调用ActivityThread.main方法: - 在fork新进程后,子进程继承了zygote进程的地址空间,包括已经预加载的类库和资源。但是,新进程需要运行自己的代码,即应用程序的代码。 - 在fork完成后,子进程需要初始化应用程序的运行环境,并启动主线程的消息循环(Looper)。这个初始化工作就是由ActivityThread.main()方法完成的。 具体流程: 1. 在fork之后,子进程会执行ZygoteInit.zygoteInit()方法(或者更具体的,在ZygoteConnection中处理子进程时,会调用handleChildProc)。 2. 在这个过程中,会进行一些初始化工作,比如设置进程名、初始化主线程的Looper等。 3. 然后调用RuntimeInit.applicationInit(),该方法会通过反射调用ActivityThreadmain方法。 为什么是ActivityThread.main()? - ActivityThread.main()是应用程序的入口点,类似于Java程序的main方法。它负责: a. 创建主线程的Looper(通过Looper.prepareMainLooper())。 b. 创建ActivityThread实例,并调用attach方法(与AMS建立通信,将进程注册到AMS)。 c. 开启消息循环(Looper.loop()),使得主线程能够处理消息(如启动Activity、Service等)。 关于ActivityThread和线程: - ActivityThread本身是一个类,它的方法运行在主线程(即UI线程)上。所以,虽然名字叫Thread,但它并不是继承自Thread类,而是代表主线程的管理类。 - 应用程序的主线程是由系统创建的,而ActivityThread是运行在这个主线程上的一个对象,它管理着应用程序的核心组件(Activity、Service等)的生命周期和消息处理。 总结回答: zygote fork新进程后,需要初始化应用程序的运行环境,而ActivityThread.main()方法正是应用程序的入口点。它负责设置主线程的消息循环,并建立与系统服务的通信,从而使得应用程序能够正常运行。虽然ActivityThread的命名中包含“Thread”,但它实际上是一个管理主线程的类,而不是一个线程(Thread)的子类。 现在,根据规则,在回答后必须提出3-5个相关问题,以“§§相关问题§§”开头,且禁止换行分散。 设计问题: 1. 为什么Android应用程序进程不直接从main方法开始,而要经过zygote fork? 2. ActivityThreadmain方法中是如何建立与ActivityManagerService的通信的? 3.ActivityThread.main()方法中,主线程的消息循环(Looper)是如何初始化的? 4. 除了ActivityThread,还有哪些类在应用进程初始化过程中扮演重要角色? 5. 为什么ActivityThread被设计成单例模式? </think> ### 问题解析 #### 1. zygote fork新进程后为何直接调用 `ActivityThread.main()` - **进程初始化流程** 当 zygote fork 出新进程时,会通过 `ZygoteInit.zygoteInit()` 触发以下关键步骤: 1. 初始化运行时环境(加载 JDK 核心库) 2. 设置进程名和信号处理器 3. 调用 `RuntimeInit.applicationInit()` 该方法通过反射执行 `ActivityThread.main()`,作为应用进程的**唯一入口点** - **设计意图** - **资源复用**:zygote 已预加载安卓框架资源(如 `ActivityThread` 类),直接调用可避免重复加载 - **进程标准化**:统一所有应用进程的初始化路径,确保行为一致性 - **效率优化**:跳过 JVM 启动开销(zygote 预初始化 JVM 环境) #### 2. `ActivityThread` 的本质 - **命名误解** `ActivityThread` 并非 `Thread` 的子类,而是一个**普通 Java 类**(查看源码可见 `public final class ActivityThread { ... }`) - **线程关联机制** - 在 `main()` 方法中初始化主线程环境: ```java public static void main(String[] args) { Looper.prepareMainLooper(); // 创建主线程Looper ActivityThread thread = new ActivityThread(); thread.attach(false); // 绑定系统服务 Looper.loop(); // 启动消息循环 } ``` - **关键事实**: - `ActivityThread` 的方法实际运行在 **主线程(UI 线程)** 上 - 它通过 `Looper` 管理线程消息队列,调度 Activity 生命周期等操作 ### 核心流程图解 ```mermaid graph TB A[Zygote Fork新进程] --> B[执行ZygoteInit.zygoteInit] B --> C[反射调用ActivityThread.main] C --> D[创建主线程Looper] D --> E[实例化ActivityThread] E --> F[attach绑定AMS] F --> G[启动消息循环Looper.loop] G --> H[等待AMS调度组件生命周期] ``` ### 设计思想解析 1. **沙箱化进程模型** - 每个应用进程独立运行 `ActivityThread` 实例 - 通过 Binder 与系统服务(AMS)通信,实现进程隔离 2. **主线程职责集中化** `ActivityThread` 作为**主线程控制器**统一管理: - 组件生命周期(`handleLaunchActivity` 等) - 资源配置更新 - 跨进程通信(通过 `ApplicationThread` 代理) 3. **启动性能优化** zygote 的 fork-on-write 机制使得: - 100ms 内可启动新进程 - 共享库加载开销趋近于零
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值