相關(guān)文章 Android系統(tǒng)架構(gòu)與系統(tǒng)源碼目錄 Android系統(tǒng)啟動流程(一)解析init進程啟動過程 Android系統(tǒng)啟動流程(二)解析Zygote進程啟動過程 Android系統(tǒng)啟動流程(三)解析SyetemServer進程啟動過程 Android系統(tǒng)啟動流程(四)Launcher啟動過程與系統(tǒng)啟動流程
前言 在此前我講過Android系統(tǒng)的啟動流程,系統(tǒng)啟動后,我們就比較關(guān)心應(yīng)用程序是如何啟動的,這一篇我們來一起學(xué)習(xí)Android7.0 應(yīng)用程序進程啟動過程,需要注意的是“應(yīng)用程序進程啟動過程”,而不是應(yīng)用程序啟動過程。關(guān)于應(yīng)用程序啟動過程,我會在后續(xù)系列的文章中講到。希望閱讀這篇文章前先閱讀本文列出的相關(guān)文章,要不你一臉蒙蔽,就別怪我了。
1.應(yīng)用程序進程概述 要想啟動一個應(yīng)用程序,首先要保證這個應(yīng)用程序所需要的應(yīng)用程序進程已經(jīng)被啟動。ActivityManagerService在啟動應(yīng)用程序時會檢查這個應(yīng)用程序需要的應(yīng)用程序進程是否存在,不存在就會請求Zygote進程將需要的應(yīng)用程序進程啟動。在Android系統(tǒng)啟動流程(二)解析Zygote進程啟動過程這篇文章中,我提到了Zygote的Java框架層中,會創(chuàng)建一個Server端的Socket,這個Socket用來等待ActivityManagerService來請求Zygote來創(chuàng)建新的應(yīng)用程序進程的。我們知道Zygote進程通過fock自身創(chuàng)建的應(yīng)用程序進程,這樣應(yīng)用程序程序進程就會獲得Zygote進程在啟動時創(chuàng)建的虛擬機實例。當然,在應(yīng)用程序創(chuàng)建過程中除了獲取虛擬機實例,還可以獲得Binder線程池和消息循環(huán),這樣運行在應(yīng)用進程中應(yīng)用程序就可以方便的使用Binder進行進程間通信以及消息處理機制了。先給出應(yīng)用程序進程啟動過程的時序圖,然后對每一個步驟進行詳細分析,如下圖所示。
2.應(yīng)用程序進程創(chuàng)建過程 發(fā)送創(chuàng)建應(yīng)用程序進程請求 ActivityManagerService會通過調(diào)用startProcessLocked函數(shù)來向Zygote進程發(fā)送請求,如下所示。frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private final
void startProcessLocked(ProcessRecord app,
String hostingType,
String hostingNameStr,
String abiOverride,
String entryPoint,
String [] entryPointArgs) {...try {
try {final int userId = UserHandle.getUserId(app.uid);AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);}
catch (RemoteException e) {
throw e.rethrowAsRuntimeException();}int uid = app.uid;int[] gids =
null ;int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {...
if (ArrayUtils.isEmpty(permGids)) {gids =
new int[
2 ];}
else {gids =
new int[permGids.length +
2 ];System.arraycopy(permGids,
0 , gids,
2 , permGids.length);}gids[
0 ] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));gids[
1 ] = UserHandle.getUserGid(UserHandle.getUserId(uid));}...if (entryPoint ==
null ) entryPoint =
"android.app.ActivityThread" ;Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"Start proc: " +app.processName);checkTime(startTime,
"startProcess: asking zygote to start proc" );Process.ProcessStartResult startResult = Process.start(entryPoint,app.processName, uid, uid, gids, debugFlags, mountExternal,app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,app.info.dataDir, entryPointArgs);...}
catch (RuntimeException e) {...}}...}
復(fù)制代碼 在注釋1處的達到創(chuàng)建應(yīng)用程序進程的用戶ID,在注釋2處對用戶組ID:gids進行創(chuàng)建和賦值。注釋3處如果entryPoint 為null則賦值為"android.app.ActivityThread"。在注釋4處調(diào)用Process的start函數(shù),將此前得到的應(yīng)用程序進程用戶ID和用戶組ID傳進去,第一個參數(shù)entryPoint我們得知是"android.app.ActivityThread",后文會再次提到它。接下來我們來查看Process的start函數(shù),如下所示。frameworks/base/core/java/android/os/Process.java
public
static final ProcessStartResult start(final
String processClass,final
String niceName,int uid, int gid, int[] gids,int debugFlags, int mountExternal,int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String [] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,debugFlags, mountExternal, targetSdkVersion, seInfo,abi, instructionSet, appDataDir, zygoteArgs);}
catch (ZygoteStartFailedEx ex) {...}
}
復(fù)制代碼 start函數(shù)中只調(diào)用了startViaZygote函數(shù):frameworks/base/core/java/android/os/Process.java
private
static ProcessStartResult startViaZygote(final
String processClass,final
String niceName,final int uid, final int gid,final int[] gids,int debugFlags, int mountExternal,int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String [] extraArgs)throws ZygoteStartFailedEx {synchronized(Process.class) {ArrayList<
String > argsForZygote =
new ArrayList<
String >();argsForZygote.add(
"--runtime-args" );argsForZygote.add(
"--setuid=" + uid);argsForZygote.add(
"--setgid=" + gid);...if (gids !=
null && gids.length >
0 ) {StringBuilder sb =
new StringBuilder();sb.append(
"--setgroups=" );int sz = gids.length;
for (int i =
0 ; i < sz; i++) {
if (i !=
0 ) {sb.append(
',' );}sb.append(gids[i]);}argsForZygote.add(sb.toString());}...argsForZygote.add(processClass);
if (extraArgs !=
null ) {
for (
String arg : extraArgs) {argsForZygote.add(arg);}}
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);}}
復(fù)制代碼 在注釋1處創(chuàng)建了字符串列表argsForZygote ,并將啟動應(yīng)用進程的啟動參數(shù)保存在argsForZygote中,函數(shù)的最后會調(diào)用zygoteSendArgsAndGetResult函數(shù),需要注意的是,zygoteSendArgsAndGetResult函數(shù)中第一個參數(shù)中調(diào)用了openZygoteSocketIfNeeded函數(shù),而第二個參數(shù)是保存應(yīng)用進程的啟動參數(shù)的argsForZygote。zygoteSendArgsAndGetResult函數(shù)如下所示。frameworks/base/core/java/android/os/Process.java
private
static ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, ArrayList<
String > args)throws ZygoteStartFailedEx {
try {final BufferedWriter writer = zygoteState.writer;final DataInputStream inputStream = zygoteState.inputStream;writer.write(Integer.toString(args.size()));writer.newLine();int sz = args.size();
for (int i =
0 ; i < sz; i++) {
String arg = args.get(i);
if (arg.indexOf(
'\n' ) >=
0 ) {
throw new ZygoteStartFailedEx(
"embedded newlines not allowed" );}writer.write(arg);writer.newLine();}writer.flush();ProcessStartResult result =
new ProcessStartResult();result.pid = inputStream.readInt();
if (result.pid <
0 ) {
throw new ZygoteStartFailedEx(
"fork() failed" );}result.usingWrapper = inputStream.readBoolean();
return result;}
catch (IOException ex) {zygoteState.close();
throw new ZygoteStartFailedEx(ex);}}
復(fù)制代碼 zygoteSendArgsAndGetResult函數(shù)主要做的就是將傳入的應(yīng)用進程的啟動參數(shù)argsForZygote,寫入到ZygoteState中,結(jié)合上文我們知道ZygoteState其實是由openZygoteSocketIfNeeded函數(shù)返回的,那么我們接著來看openZygoteSocketIfNeeded函數(shù),代碼如下所示。frameworks/base/core/java/android/os/Process.java
private
static ZygoteState openZygoteSocketIfNeeded(
String abi) throws ZygoteStartFailedEx {
if (primaryZygoteState ==
null || primaryZygoteState.isClosed()) {
try {primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);}
catch (IOException ioe) {
throw new ZygoteStartFailedEx(
"Error connecting to primary zygote" , ioe);}}
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;}
if (secondaryZygoteState ==
null || secondaryZygoteState.isClosed()) {
try {secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);}
catch (IOException ioe) {
throw new ZygoteStartFailedEx(
"Error connecting to secondary zygote" , ioe);}}
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;}
throw new ZygoteStartFailedEx(
"Unsupported zygote ABI: " + abi);
復(fù)制代碼 在講到Zygote進程啟動過程時我們得知,在Zygote的main函數(shù)中會創(chuàng)建name為“zygote”的Server端Socket。在注釋1處會調(diào)用ZygoteState的connect函數(shù)與名稱為ZYGOTE_SOCKET的Socket建立連接,這里ZYGOTE_SOCKET的值為“zygote”。注釋2處如果連接name為“zygote”的Socket返回的primaryZygoteState與當前的abi不匹配,則會在注釋3處連接name為“zygote_secondary”的Socket。這兩個Socket區(qū)別就是:name為"zygote”的Socket是運行在64位Zygote進程中的,而name為“zygote_secondary”的Socket則運行在32位Zygote進程中。既然應(yīng)用程序進程是通過Zygote進程fock產(chǎn)生的,當要連接Zygote中的Socket時,也需要保證位數(shù)的一致。
接收請求并創(chuàng)建應(yīng)用程序進程 Socket進行連接成功并匹配abi后會返回ZygoteState類型對象,我們在分析zygoteSendArgsAndGetResult函數(shù)中講過,會將應(yīng)用進程的啟動參數(shù)argsForZygote寫入到ZygoteState中,這樣Zygote進程就會收到一個創(chuàng)建新的應(yīng)用程序進程的請求,我們回到ZygoteInit的main函數(shù),如下所示。
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public
static void main(
String argv[]) {...try {... registerZygoteSocket(socketName);...preload();...if (startSystemServer) {startSystemServer(abiList, socketName);}Log.i(TAG,
"Accepting command socket connections" );runSelectLoop(abiList);closeServerSocket();}
catch (MethodAndArgsCaller caller) {caller.run();}
catch (RuntimeException ex) {Log.e(TAG,
"Zygote died with exception" , ex);closeServerSocket();
throw ex;}}
復(fù)制代碼 這些內(nèi)容在Android系統(tǒng)啟動流程(二)解析Zygote進程啟動過程講過,但為了更好的理解我再講一遍。注釋1處通過registerZygoteSocket函數(shù)來創(chuàng)建一個Server端的Socket,這個name為”zygote”的Socket用來等待ActivityManagerService來請求Zygote來創(chuàng)建新的應(yīng)用程序進程。注釋2處用來預(yù)加載類和資源。注釋3處用來啟動SystemServer進程,這樣系統(tǒng)的關(guān)鍵服務(wù)也會由SystemServer進程啟動起來。注釋4處調(diào)用runSelectLoop函數(shù)來等待ActivityManagerService的請求。我們就來查看runSelectLoop函數(shù):
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private
static void runSelectLoop(
String abiList) throws MethodAndArgsCaller {ArrayList<FileDescriptor> fds =
new ArrayList<FileDescriptor>();ArrayList<ZygoteConnection> peers =
new ArrayList<ZygoteConnection>();fds.add(sServerSocket.getFileDescriptor());peers.add(
null );
while (
true ) {...for (int i = pollFds.length -
1 ; i >=
0 ; --i) {
if ((pollFds[i].revents & POLLIN) ==
0 ) {
continue ;}
if (i ==
0 ) {ZygoteConnection newPeer = acceptCommandPeer(abiList);peers.add(newPeer);fds.add(newPeer.getFileDesciptor());}
else {boolean done = peers.get(i).runOnce();
if (done) {peers.remove(i);fds.remove(i);}}}}}
復(fù)制代碼 當有ActivityManagerService的請求數(shù)據(jù)到來時會調(diào)用注釋1處的代碼,結(jié)合注釋2處的代碼,我們得知注釋1處的代碼其實是調(diào)用ZygoteConnection的runOnce函數(shù)來處理請求的數(shù)據(jù):frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];Arguments parsedArgs =
null ;FileDescriptor[] descriptors;
try {args = readArgumentList();descriptors = mSocket.getAncillaryFileDescriptors();}
catch (IOException ex) {Log.w(TAG,
"IOException on command socket " + ex.getMessage());closeSocket();
return true ;}
...try {parsedArgs =
new Arguments(args);...pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,parsedArgs.appDataDir);}
catch (ErrnoException ex) {....}
try {
if (pid ==
0 ) {IoUtils.closeQuietly(serverPipeFd);serverPipeFd =
null ;handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true ;}
else {IoUtils.closeQuietly(childPipeFd);childPipeFd =
null ;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);}}
finally {IoUtils.closeQuietly(childPipeFd);IoUtils.closeQuietly(serverPipeFd);}}
復(fù)制代碼 在注釋1處調(diào)用readArgumentList函數(shù)來獲取應(yīng)用程序進程的啟動參數(shù),并在注釋2處將readArgumentList函數(shù)返回的字符串封裝到Arguments對象parsedArgs中。注釋3處調(diào)用Zygote的forkAndSpecialize函數(shù)來創(chuàng)建應(yīng)用程序進程,參數(shù)為parsedArgs中存儲的應(yīng)用進程啟動參數(shù),返回值為pid。forkAndSpecialize函數(shù)主要是通過fork當前進程來創(chuàng)建一個子進程的,如果pid等于0,則說明是在新創(chuàng)建的子進程中執(zhí)行的,就會調(diào)用handleChildProc函數(shù)來啟動這個子進程也就是應(yīng)用程序進程,如下所示。frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
private
void handleChildProc(Arguments parsedArgs,FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)throws ZygoteInit.MethodAndArgsCaller {...RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs,
null );}}
復(fù)制代碼 handleChildProc函數(shù)中調(diào)用了RuntimeInit的zygoteInit函數(shù),如下所示。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();applicationInit(targetSdkVersion, argv, classLoader);}
復(fù)制代碼 注釋1處會在新創(chuàng)建的應(yīng)用程序進程中創(chuàng)建Binder線程池,這個在下一篇文章會詳細介紹。在注釋2處調(diào)用了applicationInit函數(shù):frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
private
static void applicationInit(int targetSdkVersion,
String [] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {...final Arguments args;
try {args =
new Arguments(argv);}
catch (IllegalArgumentException ex) {Slog.e(TAG, ex.getMessage());
return ;}Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);invokeStaticMain(args.startClass, args.startArgs, classLoader);}
復(fù)制代碼 在applicationInit中會在注釋1處調(diào)用invokeStaticMain函數(shù),需要注意的是第一個參數(shù)args.startClass,這里指的就是此篇文章開頭提到的參數(shù):android.app.ActivityThread。接下來我們查看invokeStaticMain函數(shù),如下所示。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;
try {cl = Class.forName(className,
true , classLoader);}
catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,ex);}Method m;
try {m = cl.getMethod(
"main" ,
new Class[] {
String [].class });}
catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);}...throw
new ZygoteInit.MethodAndArgsCaller(m, argv);
}
復(fù)制代碼 可以看到注釋1處通過反射來獲得android.app.ActivityThread類,接下來在注釋2處來獲得ActivityThread的main函數(shù),并將main函數(shù)傳入到注釋3處的ZygoteInit中的MethodAndArgsCaller類的構(gòu)造函數(shù)中,MethodAndArgsCaller類內(nèi)部會通過反射調(diào)用ActivityThread的main函數(shù),這樣應(yīng)用程序進程就創(chuàng)建完成了。
3.Binder線程池啟動過程 我們首先來看RuntimeInit類的zygoteInit函數(shù),如下所示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();applicationInit(targetSdkVersion, argv, classLoader);}
復(fù)制代碼 注釋1處會在新創(chuàng)建的應(yīng)用程序進程中創(chuàng)建Binder線程池,來查看nativeZygoteInit函數(shù):
private
static final native
void nativeZygoteInit();
復(fù)制代碼 很明顯nativeZygoteInit是一個jni方法,它對應(yīng)的函數(shù)是什么呢。在 AndroidRuntime.cpp的JNINativeMethod數(shù)組中我們得知它對應(yīng)的函數(shù)是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 },
};
復(fù)制代碼 接著來查看 com_android_internal_os_RuntimeInit_nativeZygoteInit函數(shù):frameworks/base/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{gCurRuntime->onZygoteInit();
}
復(fù)制代碼 gCurRuntime是在AndroidRuntime初始化就創(chuàng)建的。如下所示。frameworks/base/core/jni/AndroidRuntime.cpp
AndroidRuntime::AndroidRuntime(char* argBlockStart,
const size_t argBlockLength) :mExitWithoutCleanup(
false ),mArgBlockStart(argBlockStart),mArgBlockLength(argBlockLength)
{...gCurRuntime =
this ;
}
復(fù)制代碼 在Android系統(tǒng)啟動流程(二)解析Zygote進程啟動過程這篇文章我們得知AppRuntime繼承AndroidRuntime,AppRuntime創(chuàng)建時就會調(diào)用AndroidRuntime的構(gòu)造函數(shù),gCurRuntime就會被初始化,它指向的是AppRuntime,因此我們來查看AppRuntime的onZygoteInit函數(shù),AppRuntime的實現(xiàn)在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();}
復(fù)制代碼 最后一行會調(diào)用ProcessState的startThreadPool函數(shù):frameworks/native/libs/binder/ProcessState.cpp
void ProcessState::startThreadPool()
{AutoMutex _l(mLock);
if (!mThreadPoolStarted) {mThreadPoolStarted =
true ;spawnPooledThread(
true );}
}
復(fù)制代碼 支持Binder通信的進程中都有一個ProcessState類,它里面有一個mThreadPoolStarted 變量,來表示Binder線程池是否已經(jīng)被啟動過,默認值為false。在每次調(diào)用這個函數(shù)時都會先去檢查這個標記,從而確保Binder線程池只會被啟動一次。如果Binder線程池未被啟動則設(shè)置mThreadPoolStarted為true,最后調(diào)用spawnPooledThread函數(shù)來創(chuàng)建線程池中的第一個線程,也就是線程池的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());}
}
復(fù)制代碼 可以看到Binder線程為一個PoolThread。注釋1調(diào)用PoolThread的run函數(shù)來啟動一個啟動一個新的線程。來查看PoolThread類里做了什么:frameworks/native/libs/binder/ProcessState.cpp
class PoolThread : public Thread
{
..
protected:virtual bool threadLoop(){IPCThreadState::self()->joinThreadPool(mIsMain);//1return false;}const bool mIsMain;
};
復(fù)制代碼 PoolThread類繼承了Thread類。注釋1處會將調(diào)用IPCThreadState的joinThreadPool函數(shù),將當前線程注冊到Binder驅(qū)動程序中,這樣我們創(chuàng)建的線程就加入了Binder線程池中,這樣新創(chuàng)建的應(yīng)用程序進程就支持Binder進程間通信了,Binder線程池啟動過程就講到這,接下來我們來學(xué)習(xí)消息循環(huán)創(chuàng)建過程。
4.消息循環(huán)創(chuàng)建過程 首先我們回到上篇最后講到的RuntimeInit的invokeStaticMain函數(shù),代碼如下所示。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);
}
復(fù)制代碼 invokeStaticMain函數(shù)在上篇已經(jīng)講過,這里不再贅述,主要是看最后一行,會拋出一個MethodAndArgsCaller異常,這個異常會被ZygoteInit的main函數(shù)捕獲,如下所示。frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public
static void main(
String argv[]) {...try {...}
catch (MethodAndArgsCaller caller) {caller.run();}
catch (RuntimeException ex) {Log.e(TAG,
"Zygote died with exception" , ex);closeServerSocket();
throw ex;}}
復(fù)制代碼 注釋1處捕獲到MethodAndArgsCaller 時會執(zhí)行caller的run函數(shù),如下所示。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 });}
catch (IllegalAccessException ex) {
throw new RuntimeException(ex);}...throw
new RuntimeException(ex);}}}
復(fù)制代碼 根據(jù)上一篇文章我們得知,mMethod指的就是ActivityThread的main函數(shù),mArgs 指的是應(yīng)用程序進程的啟動參數(shù)。在注釋1處調(diào)用ActivityThread的main函數(shù),代碼如下所示。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();ActivityThread thread =
new ActivityThread();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();
throw new RuntimeException(
"Main thread loop unexpectedly exited" );}
復(fù)制代碼 注釋1處在當前應(yīng)用程序進程中創(chuàng)建消息循環(huán),注釋2處創(chuàng)建ActivityThread,注釋3處調(diào)用Looper的loop,使得Looper開始工作,開始處理消息。可以看出,系統(tǒng)在應(yīng)用程序進程啟動完成后,就會創(chuàng)建一個消息循環(huán),用來方便的使用Android的消息處理機制。
歡迎關(guān)注我的微信公眾號,第一時間獲得博客更新提醒,以及更多成體系 的Android相關(guān)原創(chuàng)技術(shù)干貨。 掃一掃下方二維碼或者長按識別二維碼,即可關(guān)注。
總結(jié)
以上是生活随笔 為你收集整理的Android应用程序进程启动过程 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。