zygote本身是一個Native應用程式,在Android.mk中指定的名字是app_process,源碼位置:
framework/base/cmds/app_process/App_main.cpp
該代碼重要功能是由AppRuntime的start完成的,而這個函數使用的是基類AndroidRuntime的start,分析AndroidRuntime:
1、建立虛擬機器,調用Jni建立。JNI_CreateJavaVM
2、給虛擬機器註冊JNI函數,startReg
在zygoteinit.java中進入java世界,不再返回Native,
1、建立IPC通訊服務端-registerZygoteSocket,建立一個服務端的socket
2、preloadClass和preloadresources,預先載入類和資源,這裡預先載入類有很多,載入preloaded-classes檔案的內容,是導致android系統啟動慢的原因之一。preloadResources主要載入framework-res.apk中的資源
3、啟動system_server,建立了一個子進程處理java
4、runSelectLoopMode,這裡補充下socket的知識,socket中有兩種方式觸發讀資料,第一種:使用listen()去監聽某個連接埠,再read從該連接埠讀資料,這種方式稱為阻塞式讀操作,因為當連接埠沒有資料時,read函數將一直等待,直到有資料才返回;第二種:使用select函數將需要監聽的檔案描述符作為select函數的參數,當檔案描述符中出現新的資料,自動觸發一個中斷,然後在中斷處理中去讀制定檔案描述符的資料,這種方式為非阻塞式操作。而這裡使用的是第二種。而用戶端用ZygoteConnection來表示,在runOnce中處理。
對SystemServer進行分析:
通過Zygote.forkSystemServer函數fork出一個新的進程,setSignalHandler設定訊號處理函數,使子進程SystemServer和Zygote一同開啟,一同結束。建立完進程後,執行handleSystemServerProcess,與Binder通訊建立聯絡。然後調用systemserver的main函數。fork的返回值大於0時,代表父進程,返回值等於0時,代表複製的子進程。調用invokeStaticMain函數拋出異常,在ZygoteInit的main中捕獲,調用systemserver的main函數。
總結:Zygote fork出進程SystemServer主要是為了調用main函數,載入libandroid_server.so 庫,init1是native函數,將調用線程加入Bindle通訊中,init2單獨建立一個線程,啟動系統的各項服務
以一個Activity的啟動為例,zygote是怎麼處理的:
ActivityManagerService是由SystemServer建立的,假如通過startActivity啟動一個新的Activity,會先調用ActivityManagerService的startProcessLocked,最終調用zygoteSendArgsAndGeiPid開啟和zygote通訊的socket,並向該socket發送資料請求,此時,ZygoteInit中runSelectLoopMode正在用非阻塞的方式等待資料,有資料來時,調用runOnce處理,在runOnce中fork出一個新的進程,然後調用invokeStaticMain函數拋出異常,調用systemserver的main函數繼續等待請求下一次分裂。
注意:
建立虛擬機器時,heapsize的限制,一般為最大值16MB或者32MB
開機速度最佳化:
1、ZygoteInit中載入了preloadclasses有1000多個類,耗費時間太多;
2、preloadresources對所有apk檔案進行載入;
3、SystemServer建立的Service有很多,像AMS等等。
wait和notify:
synchronized(obj) {while(!condition) {obj.wait();} obj.doSomething();}
當線程A獲得了obj鎖後,發現條件condition不滿足,無法繼續下一處理,於是線程A就wait()。當另一線程擷取到obj鎖後,改變條件,可以喚醒A
synchronized(obj) {condition = true;obj.notify();}