1. 程式人生 > >Android應用程式程序啟動過程(後篇)

Android應用程式程序啟動過程(後篇)

前言

在前篇中我們講到了Android應用程式程序啟動過程,這一篇我們來講遺留的知識點:在應用程式程序建立過程中會啟動Binder執行緒池以及在應用程式程序啟動後會建立訊息迴圈。

1.Binder執行緒池啟動過程

我們首先來看RuntimeInit類的zygoteInit函式,如下所示
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

  public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws
ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit"); redirectLogStreams(); commonInit(); nativeZygoteInit();//1 applicationInit(targetSdkVersion, argv, classLoader); }

註釋1處會在新建立的應用程式程序中建立Binder執行緒池,來檢視nativeZygoteInit函式:

 private static final native void nativeZygoteInit();

很明顯nativeZygoteInit是一個jni方法,它對應的函式是什麼呢。在 AndroidRuntime.cpp的JNINativeMethod陣列中我們得知它對應的函式是com_android_internal_os_RuntimeInit_nativeZygoteInit,如下所示。
frameworks/base/core/jni/AndroidRuntime.cpp

static const JNINativeMethod gMethods[] = {
    { "nativeFinishInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
    { "nativeZygoteInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
    { "nativeSetExitWithoutCleanup", "(Z)V",
        (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};

接著來檢視 com_android_internal_os_RuntimeInit_nativeZygoteInit函式:
frameworks/base/core/jni/AndroidRuntime.cpp

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

gCurRuntime是在AndroidRuntime初始化就建立的。如下所示。
frameworks/base/core/jni/AndroidRuntime.cpp

AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
        mExitWithoutCleanup(false),
        mArgBlockStart(argBlockStart),
        mArgBlockLength(argBlockLength)
{
   ...
    gCurRuntime = this;
}

Android系統啟動流程(二)解析Zygote程序啟動過程這篇文章我們得知AppRuntime繼承AndroidRuntime,AppRuntime建立時就會呼叫AndroidRuntime的建構函式,gCurRuntime就會被初始化,它指向的是AppRuntime,因此我們來檢視AppRuntime的onZygoteInit函式,AppRuntime的實現在app_main.cpp中,如下所示。
frameworks/base/cmds/app_process/app_main.cpp

 virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }

最後一行會呼叫ProcessState的startThreadPool函式:
frameworks/native/libs/binder/ProcessState.cpp

void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}

支援Binder通訊的程序中都有一個ProcessState類,它裡面有一個mThreadPoolStarted 變數,來表示Binder執行緒池是否已經被啟動過,預設值為false。在每次呼叫這個函式時都會先去檢查這個標記,從而確保Binder執行緒池只會被啟動一次。如果Binder執行緒池未被啟動則設定mThreadPoolStarted為true,最後呼叫spawnPooledThread函式來建立執行緒池中的第一個執行緒,也就是執行緒池的main執行緒,如下所示。
frameworks/native/libs/binder/ProcessState.cpp

void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        ALOGV("Spawning new pooled thread, name=%s\n", name.string());
        sp<Thread> t = new PoolThread(isMain);
        t->run(name.string());//1
    }
}

可以看到Binder執行緒為一個PoolThread。註釋1呼叫PoolThread的run函式來啟動一個啟動一個新的執行緒。來檢視PoolThread類裡做了什麼:
frameworks/native/libs/binder/ProcessState.cpp

class PoolThread : public Thread
{
..
protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);//1
        return false;
    }
    const bool mIsMain;
};

PoolThread類繼承了Thread類。註釋1處會將呼叫IPCThreadState的joinThreadPool函式,將當前執行緒註冊到Binder驅動程式中,這樣我們建立的執行緒就加入了Binder執行緒池中,這樣新建立的應用程式程序就支援Binder程序間通訊了,Binder執行緒池啟動過程就講到這,接下來我們來學習訊息迴圈建立過程。

2.訊息迴圈建立過程

首先我們回到上篇最後講到的RuntimeInit的invokeStaticMain函式,程式碼如下所示。
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl;
  ...
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

invokeStaticMain函式在上篇已經講過,這裡不再贅述,主要是看最後一行,會丟擲一個MethodAndArgsCaller異常,這個異常會被ZygoteInit的main函式捕獲,如下所示。
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

  public static void main(String argv[]) {
     ...
        try {
           ...
        } catch (MethodAndArgsCaller caller) {
            caller.run();//1
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

註釋1處捕獲到MethodAndArgsCaller 時會執行caller的run函式,如下所示。
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

 public static class MethodAndArgsCaller extends Exception
            implements Runnable {
        private final Method mMethod;
        private final String[] mArgs;
        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }
        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });//1
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            }
            ...
                throw new RuntimeException(ex);
            }
        }
    }

根據上一篇文章我們得知,mMethod指的就是ActivityThread的main函式,mArgs 指的是應用程式程序的啟動引數。在註釋1處呼叫ActivityThread的main函式,程式碼如下所示。
frameworks/base/core/java/android/app/ActivityThread.java

 public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();
...
        Looper.prepareMainLooper();//1
        ActivityThread thread = new ActivityThread();//2
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();//3
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

註釋1處在當前應用程式程序中建立訊息迴圈,註釋2處建立ActivityThread,註釋3處呼叫Looper的loop,使得Looper開始工作,開始處理訊息。可以看出,系統在應用程式程序啟動完成後,就會建立一個訊息迴圈,用來方便的使用Android的訊息處理機制。

歡迎關注我的微信公眾號,第一時間獲得部落格更新提醒,以及更多成體系的Android相關原創技術乾貨。
掃一掃下方二維碼或者長按識別二維碼,即可關注。