在這張簡圖中能夠看到,從Launcher點擊圖標啓動進程涉及到了3個角色。 其中Launcher是發起請求進程(caller),AMS接收到Launcher的請求並處理,若是要啓動的Activity的進程不存在,則經過本地套接字鏈接到Zygote,向Zygote發起建立進程的請求。Zygote接收該請求並fork出app進程。java
整個過程涉及到的細節比較多,咱們這裏只關注核心部分,分紅幾個小節來講。linux
Zygote是android系統中的一個重要的守護進程,它的主要做用是:
① 建立VM實例、預加載類和資源等。
② 啓動systemserver。
③ 建立本地套接字,等待AMS的fork請求,完成app進程的建立工做。android
下面咱們簡單看下它的源碼:數據結構
// frameworks/base/cmds/app_process/app_main.cpp int main(int argc, const char* const argv[]) { AppRuntime runtime; ... if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", startSystemServer ? "start-system-server" : ""); } ... }
AppRuntime的start()函數繼承自基類AndroidRuntime,即上述代碼將跳到app
// frameworks/base/core/jni/AndroidRuntime.cpp void AndroidRuntime::start(const char* className, const char* options) { ... JNIEnv* env; // 啓動虛擬機 if (startVm(&mJavaVM, &env) != 0) { return; } // 註冊android須要的jni函數 if (startReg(env) < 0) { LOGE("Unable to register all android natives\n"); return; } ... // className是com.android.internal.os.ZygoteInit char* slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { LOGE("JavaVM unable to locate class '%s'\n", slashClassName); } else { jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { LOGE("JavaVM unable to find main() in '%s'\n", className); } else { // 調用ZygoteInit的main(String[])方法 env->CallStaticVoidMethod(startClass, startMeth, strArray); } } free(slashClassName); ... }
好了,到這一步,虛擬機已經啓動起來了,開始加載並運行主類(ZygoteInit)的main()函數了。socket
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java public static void main(String argv[]) { try { // 建立本地套接字 registerZygoteSocket(); // 預加載類和資源等 preload(); ... if (argv[1].equals("start-system-server")) { // 啓動system server進程 startSystemServer(); } else if (!argv[1].equals("")) { throw new RuntimeException(argv[0] + USAGE_STRING); } ... // 建立一個本地套接字,等待客戶端的請求 runSelectLoopMode(); closeServerSocket(); } catch (MethodAndArgsCaller caller) { // fork()出來的子進程最終會走到這 // 在這個裏面經過反射調用對應主類(即ActivityThread)的main()方法 caller.run(); } catch (RuntimeException ex) { closeServerSocket(); throw ex; } }
private static void runSelectLoopMode() throws MethodAndArgsCaller { // fds--peers 每一項是一一對應的,即<文件描述符,已創建的鏈接>構成一個二元組 ArrayList<FileDescriptor> fds = new ArrayList(); ArrayList<ZygoteConnection> peers = new ArrayList(); FileDescriptor[] fdArray = new FileDescriptor[4]; // 第一個二元組是<socket監聽描述符,null> fds.add(sServerSocket.getFileDescriptor()); peers.add(null); while (true) { ... try { fdArray = fds.toArray(fdArray); // native方法,使用了select io多路複用機制 index = selectReadable(fdArray); } catch (IOException ex) { throw new RuntimeException("Error in select()", ex); } if (index < 0) { throw new RuntimeException("Error in select()"); } else if (index == 0) { // index爲0的是socket監聽描述符,selectReadable()返回0表示來了個新鏈接 ZygoteConnection newPeer = acceptCommandPeer(); // 將創建好的新鏈接的二元組添加到集合中 peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { // index>0表示已鏈接描述符有收到數據了 boolean done; // 讓對應的鏈接來處理數據 done = peers.get(index).runOnce(); if (done) { peers.remove(index); fds.remove(index); } } } }
到這一步,Zygote的大致啓動流程咱們已經分析完了。關於Zygote如何建立app進程,咱們放到後面AMS那塊再說。函數
ActivityManagerService,簡稱AMS。見名知意,它是用來管理Activity的系統服務。就像linux內核使用task_struct來管理進程同樣,AMS要管理Activity,它確定須要用某種數據結構來記錄當前系統上Activity的信息。oop
記錄每一個Activity的運行時信息
final class ActivityRecord extends IApplicationToken.Stub { final ActivityManagerService service; // 從AndroidManifest.xml解析出來的關於Activity的信息 final ActivityInfo info; // 觸發生成這個ActivityRecord的Intent final Intent intent; // 當前activity所屬的任務棧 TaskRecord task; // 當前Activity所屬進程的信息 ProcessRecord app; ... }
記錄當前正在運行的某個進程的完整信息
class ProcessRecord { // 進程名和進程id final String processName; int pid; // AMS經過該Binder接口向app進程發請求 IApplicationThread thread; ... }
Launcher向AMS發起startActivity請求後,AMS會作一系列處理,這裏咱們只關心下面2個要點:
① AMS會建立一個ActivityRecord對象來記錄該Activity的信息。
② 若是進程不存在,即對應的ProcessRecord對象不存在,則建立ProcessRecord來記錄要新建的進程的信息,並向Zygote請求建立新進程。進程建立成功後,在ProcessRecord中記錄下Zygote返回新進程的pid。ui
// frameworks/base/services/java/com/android/server/am/ActivityStack.java final int startActivityLocked(IApplicationThread caller, Intent intent, String resolvedType, Uri[] grantedUriPermissions, int grantedMode, ActivityInfo aInfo, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, boolean onlyIfNeeded, boolean componentSpecified, ActivityRecord[] outActivity) { ... // 建立即將要啓動的Activity的相關信息,並保存在r變量中 ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified); ... }
// frameworks/base/services/java/com/android/server/am/ActivityStack.java private final void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // AMS維護了一個ProcessMap<ProcessRecord> mProcessNames,用來記錄經過AMS啓動並運行的app進程 // 在這個map裏沒查到說明該app進程不存在 ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid); ... if (app != null && app.thread != null) { // 應用進程存在,則啓動對應的Activity try { app.addPackage(r.info.packageName); realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e); } } // 應用進程不存在,先建立進程 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false); }
// frameworks/base/services/java/com/android/server/am/ActivityManagerService.java final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting) { ... if (app == null) { // 建立一個ProcessRecord,用來記錄要啓動的進程的信息 app = newProcessRecordLocked(null, info, processName); // 將ProcessRecord存入map中 mProcessNames.put(processName, info.uid, app); } ... startProcessLocked(app, hostingType, hostingNameStr); ... } private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) { // 使用Process.start來啓動新進程 Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread", app.processName, uid, uid, gids, debugFlags, app.info.targetSdkVersion, null); ... app.pid = startResult.pid; // 記錄新進程的pid ... }
剛纔上面咱們沒有看到有關和Zygote socket相關的內容。這塊實際上是由ZygoteProcess類實現的。Process.start()通過幾層調用,來到ZygoteProcess.startViaZygote()`。this
Process.start() --> ZygoteProcess.start() --> ZygoteProcess.startViaZygote()
private Process.ProcessStartResult startViaZygote(...) { ... // 省略參數的組裝過程 synchronized(mLock) { return zygoteSendArgsAndGetResult( openZygoteSocketIfNeeded(abi), // 創建socket鏈接 argsForZygote); // argsForZygote是要發給Zygote的參數,ArrayList類型 }
private static Process.ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, ArrayList<String> args) throws ZygoteStartFailedEx { ... // 寫入流 final BufferedWriter writer = zygoteState.writer; // 讀取流 final DataInputStream inputStream = zygoteState.inputStream; // 按照Zygote協議寫數據 // 先寫入參數個數,格式:size\n writer.write(Integer.toString(args.size())); writer.newLine(); // 寫參數,每一個參數的格式:arg\n for (int i = 0; i < sz; i++) { String arg = args.get(i); writer.write(arg); writer.newLine(); } writer.flush(); Process.ProcessStartResult result = new Process.ProcessStartResult(); // 讀取Zygote返回回來的進程id result.pid = inputStream.readInt(); if (result.pid < 0) { // 若是pid小於0,說明fork失敗了 throw new ZygoteStartFailedEx("fork() failed"); } return result; }
ProcessProcess向Zygote發送請求和接收請求的大體流程咱們已經看過了。那Zygote那邊怎麼接收和處理請求的呢?
// frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { try { // 讀取client經過socket發過來的數據 args = readArgumentList(); descriptors = mSocket.getAncillaryFileDescriptors(); } catch (IOException ex) { Log.w(TAG, "IOException on command socket " + ex.getMessage()); closeSocket(); return true; } ... // 將獲取的數據解析成Arguments類型 parsedArgs = new Arguments(args); ... // 建立APP進程 pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits); if (pid == 0) { ... // 走子進程的處理邏輯 handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); ... } else { ... // 走父進程的處理邏輯 return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); } }
此時進程已經建立好了,須要將子進程的pid經過socket傳回給AMS了。
// frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java private boolean handleParentProc(int pid, FileDescriptor[] descriptors, FileDescriptor pipeFd, Arguments parsedArgs) { ... try { // 將fork出來的進程pid傳給AMS mSocketOutStream.writeInt(pid); mSocketOutStream.writeBoolean(usingWrapper); } catch (IOException ex) { Log.e(TAG, "Error reading from command socket", ex); return true; } ... }
上面的流程結束後,子進程已經成功建立,接下來子進程將進行自身的初始化,加載主類和執行main(String[])方法。
ZygoteConnection.handleChildProc() --> RuntimeInit.zygoteInit() --> RuntimeInit.zygoteInitNative() --> RuntimeInit.applicationInit() --> RuntimeInit.invokeStaticMain()
private static void invokeStaticMain(String className, String[] argv) throws ZygoteInit.MethodAndArgsCaller { Class<?> cl; // 加載主類(android.app.ActivityThread) cl = Class.forName(className); Method m; // 獲取main(String[])方法 m = cl.getMethod("main", new Class[] { String[].class }); // 檢查main方法是不是public static的 int modifiers = m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { throw new RuntimeException( "Main method is not public and static on " + className); } // 拋出異常,返回到ZygoteInit.main()的catch塊中繼續執行 throw new ZygoteInit.MethodAndArgsCaller(m, argv); }
這段代碼的最後將反射獲得的Method對象和參數封裝成ZygoteInit.MethodAndArgsCaller異常並拋出,這個異常被ZygoteInit的main()方法捕獲。
// ZygoteInit.main() catch (MethodAndArgsCaller caller) { // fork()出來的子進程最終會走到這 // 在這個裏面經過反射調用對應類的main()方法 caller.run(); } // MethodAndArgsCaller.run() public void run() { try { // 最終經過反射調用main()方法 mMethod.invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { throw new RuntimeException(ex); } }
最終,app進程的ActivityThread類的main()方法開始執行。