之前花過一段時(shí)間整理了下Android系統(tǒng)啟動(dòng)、Activity啟動(dòng)以及ActivityThread等系統(tǒng)內(nèi)容伏嗜。時(shí)間久遠(yuǎn)坛悉,很多細(xì)節(jié)都忘了,本著互聯(lián)共享的精神承绸,在這里把之前的文檔重新整理裸影。計(jì)劃寫三篇文章:《夢(mèng)幻曲:Android系統(tǒng)啟動(dòng)》,《沉思曲:Activity啟動(dòng)》军熏、《小夜曲:ActivityThread分析》轩猩,一家之言難免有各種問題,僅供參考荡澎。
參考 | http://blog.csdn.net/jeffbao/article/details/18242515
概念
Dalvik虛擬機(jī)
當(dāng)java程序運(yùn)行時(shí)均践,都是有一個(gè)虛擬機(jī)來解釋java的字節(jié)碼,它將這些字節(jié)碼翻譯成本地CPU的指令碼摩幔,然后執(zhí)行彤委。
AndroidRuntime
歸納起來的意思就是,Runtime 是支撐程序運(yùn)行的基礎(chǔ)庫或衡,它是與語言綁定在一起的焦影。比如:
- C Runtime:就是C standard lib,也就是我們常說的libc封断。(有意思的是斯辰, Wiki會(huì)自動(dòng)將“C runtime" 重定向到 "C Standard Library")。
- Java Runtime: 同樣坡疼,Wiki將其重定向到” Java Virtual Machine"彬呻,這里當(dāng)然包括Java 的支撐類庫(.jar)。
-
AndroidRuntime: 顯而易見柄瑰,就是為Android應(yīng)用運(yùn)行所需的運(yùn)行時(shí)環(huán)境废岂。包括:
- Dalvik VM: Android的Java VM,解釋運(yùn)行Dex格式Java程序狱意。每個(gè)進(jìn)程運(yùn)行一個(gè)虛擬機(jī)(什么叫運(yùn)行虛擬機(jī)湖苞?說白了,就是一些C代碼详囤,不停的去解釋Dex格式的二進(jìn)制碼(Bytecode)财骨,把它們轉(zhuǎn)成機(jī)器碼(Machine code),然后執(zhí)行藏姐。
- 當(dāng)然隆箩,現(xiàn)在大多數(shù)的Java 虛擬機(jī)都支持JIT,也就是說羔杨,byte code可能在運(yùn)行前就已經(jīng)被轉(zhuǎn)換成機(jī)器碼捌臊,從而大大提高了性能。過去一個(gè)普遍的認(rèn)識(shí)是Java 程序比C兜材,C++等靜態(tài)編譯的語言慢理澎,但隨著JIT的介入和發(fā)展逞力,這個(gè)已經(jīng)完全是過去時(shí)了,JIT的動(dòng)態(tài)性運(yùn)行允許虛擬機(jī)根據(jù)運(yùn)行時(shí)環(huán)境糠爬,優(yōu)化機(jī)器碼的生成寇荧,在某些情況下,Java甚至可以比C/C++跑得更快执隧,同時(shí)又兼具平臺(tái)無關(guān)的特性揩抡,這也是為什么Java如今如此流行的原因之一吧)。
- Android的Java 類庫, 大部分來自于 Apache Hamony, 開源的Java API 實(shí)現(xiàn)镀琉,如 java.lang, java.util, java.net. 但去除了AWT, Swing 等部件峦嗤。
- JNI: C和Java互調(diào)的接口。
- Libc: Android也有很多C代碼屋摔,自然少不了libc烁设,注意的是,Android的libc叫 bionic C.
- Dalvik VM: Android的Java VM,解釋運(yùn)行Dex格式Java程序狱意。每個(gè)進(jìn)程運(yùn)行一個(gè)虛擬機(jī)(什么叫運(yùn)行虛擬機(jī)湖苞?說白了,就是一些C代碼详囤,不停的去解釋Dex格式的二進(jìn)制碼(Bytecode)财骨,把它們轉(zhuǎn)成機(jī)器碼(Machine code),然后執(zhí)行藏姐。
圖
框架圖
在往下講之前凡壤,先看下框架圖:
代碼流程圖
init進(jìn)程
init進(jìn)程的啟動(dòng)配置在init.rc文件中署尤,
note:init.rc文件的語法可參考:init.rc分析
1.1、init進(jìn)程啟動(dòng)ServiceManager
/*service后第一個(gè)參數(shù)為進(jìn)程名亚侠,第二個(gè)參數(shù)為進(jìn)程路徑曹体,后面參數(shù)為啟動(dòng)改進(jìn)程傳遞的參數(shù)*/
//service關(guān)鍵字啟動(dòng)servicemanager
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
- Servicemanager負(fù)責(zé)管理所有的服務(wù)(native service、java service)硝烂,如服務(wù)的注冊(cè)箕别、查找等。
- native service主要有: surfaceflinger滞谢、drm串稀、media等。
- java service主要有:ActivityManagerService狮杨、WindowManagerService母截、PowerManagerService等。
- 其中橄教,native service大多在init.rc文件中由service關(guān)鍵字創(chuàng)建啟動(dòng)清寇;java service大多由zygote創(chuàng)建啟動(dòng)。
1.2护蝶、init進(jìn)程啟動(dòng)Zygote
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
- 由service第二個(gè)參數(shù)可知华烟,此處啟動(dòng)的進(jìn)程為zygote進(jìn)程,并由app_process實(shí)現(xiàn)持灰。
- zygote由java編寫盔夜,不能有init進(jìn)程直接啟動(dòng);必須先生成Dalvik虛擬機(jī),再在Dalvik虛擬機(jī)中裝載zygote的實(shí)現(xiàn)類(ZygoteInit.java)喂链。
Zygote進(jìn)程
在往下講Zygote進(jìn)程前返十,先看附圖,了解下Zygote都做啥了:
Zygote進(jìn)程的入口在app_main.cpp文件的main方法中衩藤,看下其main方法
2.1 main | app_main.cpp
int main(int argc, char* const argv[])
{
...
//解析入?yún)陕颂幦雲(yún)椤?-zygote --start-system-server”
while (i < argc) {
const char* arg = argv[i++];
if (!parentDir) {
parentDir = arg;
} else if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = "zygote";
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName = arg + 12;
} else {
className = arg;
break;
}
}
//設(shè)置進(jìn)程名
if (niceName && *niceName) {
setArgv0(argv0, niceName);
set_process_name(niceName);
}
runtime.mParentDir = parentDir;
if (zygote) {
//start生成并初始化Dalvik虛擬機(jī)涛漂,并加載ZygoteInit類到虛擬機(jī)中
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
runtime.mClassName = className;
runtime.mArgC = argc - i;
runtime.mArgV = argv + i;
//加載RuntimeInit類到虛擬機(jī)中
runtime.start("com.android.internal.os.RuntimeInit",
application ? "application" : "tool");
} else {
app_usage();
return 10;
}
}
- 入?yún)椤?-zygote --start-system-server”赏表,通過調(diào)用runtime.start創(chuàng)建和生成Dalvik虛擬機(jī),并加載ZygoteInit類到虛擬機(jī)中匈仗。
- 加載ZygoteInit類瓢剿,調(diào)用其main方法,啟動(dòng)SystemServer悠轩。
2.2间狂、main | ZygoteInit.java
public static void main(String argv[]) {
try {
//注冊(cè)server socket
//其它進(jìn)程的創(chuàng)建,通過連接到該Socket后,由zygote孵化
registerZygoteSocket();
...
//預(yù)加載android framework類和資源
preload();
...
if (argv[1].equals("start-system-server")) {
//啟動(dòng)SystemServer
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
//死循環(huán)接收client socket連接火架,由此創(chuàng)建新進(jìn)程
runSelectLoop();
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
closeServerSocket();
throw ex;
}
}
- 入?yún)?start-system-server"鉴象,Zygote進(jìn)程調(diào)用 startSystemServer()方法啟動(dòng)SystemServer。
2.3何鸡、startSystemServer
startSystemServer方法在ZygoteInit.java中纺弊,看方法名是要啟動(dòng)SystemServer進(jìn)程了。
private static boolean startSystemServer()
throws MethodAndArgsCaller, RuntimeException {
...
//啟動(dòng)systemServer的參數(shù)
String args[] = {
"--setuid=1000",
"--setgid=1000",
"-- setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
//啟動(dòng)的SystemServer全限定名骡男,后續(xù)根據(jù)該參數(shù)反射創(chuàng)建實(shí)例
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
/**
* 將傳入?yún)?shù)進(jìn)行轉(zhuǎn)換
* 注意:參數(shù)com.android.server.SystemServer 放在parsedArgs中的remainingArgs里
*/
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
//Zygote為SystemServer創(chuàng)建子進(jìn)程
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
//子進(jìn)程執(zhí)行
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
return true;
}
- Zygote為SystemServer創(chuàng)建新進(jìn)程淆游,并在新進(jìn)程中調(diào)用handleSystemServerProcess。
SystemServer進(jìn)程
上一步中調(diào)用了handleSystemServerProcess方法隔盛。
3.1犹菱、handleSystemServerProcess
該方法在ZygoteInit.java文件中
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
//關(guān)閉SystemServer進(jìn)程的serversocket
//SystemServer進(jìn)程基礎(chǔ)了父進(jìn)程zygote所有資源
closeServerSocket();
//設(shè)置文件權(quán)限
Libcore.os.umask(S_IRWXG | S_IRWXO);
//設(shè)置新進(jìn)程名
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
null, parsedArgs.remainingArgs);
} else {
//remainArgs中包含SystemServer的全限定名:com.android.server.SystemServer
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
}
- 新進(jìn)程中接著調(diào)用RuntimeInit.zygoteInit方法
3.2、RuntimeInit.zygoteInit
RuntimeInit.zygoteInit為靜態(tài)方法吮炕,在RuntimeInit.java文件中腊脱。
public static final void zygoteInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
redirectLogStreams();
commonInit();
nativeZygoteInit();
//調(diào)用該方法,往下執(zhí)行
applicationInit(targetSdkVersion, argv);
}
3.3龙亲、applicationInit
上方法接著調(diào)用了applicationInit方法陕凹,該方法在RuntimeInit.java文件中。
private static void applicationInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
//應(yīng)用調(diào)用System.exit(),退出進(jìn)程
nativeSetExitWithoutCleanup(true);
//設(shè)置堆
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
return;
}
//創(chuàng)建args.startClass實(shí)例俱笛,并調(diào)用其main方法
invokeStaticMain(args.startClass, args.startArgs);
}
- 該方法接著調(diào)用invokeStaticMain方法捆姜,注意:此處args.startClass為com.android.server.SystemServer
3.4、invokeStaticMain
上方法接著調(diào)用了invokeStaticMain方法迎膜,該方同樣在RuntimeInit.java中泥技。看方法名磕仅,似乎是反射調(diào)用main方法珊豹。
private static void invokeStaticMain(String className, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
try {
//全限定名簸呈,此處傳入為"com.android.server.SystemServer"
cl = Class.forName(className);
}
...
Method m;
try {
//main方法
m = cl.getMethod("main", new Class[] { String[].class });
}
...
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/**
* 該異常會(huì)在ZygoteInit.main()中被捕獲,
* 捕獲后會(huì)觸發(fā)MethodAndArgsCaller的run()方法店茶,
* run方法中完成類main方法的調(diào)用
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
- 該方法最后通過拋異常的方式蜕便,拋出異常MethodAndArgsCaller;該異常被Zygote捕獲贩幻,捕獲后調(diào)用該異常的run方法轿腺,而在run放中完成類main方法的調(diào)用。
- 因此丛楚,該步最后調(diào)用SystemServer的main方法族壳。
3.5、main | SystemServer.java
終于調(diào)用SystemServer的main方法了趣些,看下其java層代碼主要干啥了仿荆。
public static void main(String[] args) {
...
//SystemServer需要一直運(yùn)行,因此它需要有效的利用內(nèi)存
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
Environment.setUserRequired(true);
System.loadLibrary("android_servers");
//初始化native服務(wù)
nativeInit();
//ServerThread并非Thread坏平,它只是運(yùn)行在SystemServer進(jìn)程的主線程中
ServerThread thr = new ServerThread();
//調(diào)用該方法初始化和循環(huán)處理
thr.initAndLoop();
}
3.6拢操、initAndLoop
上面方法的主要內(nèi)容在initAndLoop方法中,該方法是SystemServer的內(nèi)部類ServerThread的方法舶替。
public void initAndLoop() {
...
//main looper
Looper.prepareMainLooper();
...
try {
//啟動(dòng)DisplayManagerService服務(wù)令境,并注冊(cè)到ServiceManager
display = new DisplayManagerService(context, wmHandler);
ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
//啟動(dòng)TelephonyRegistry服務(wù),并注冊(cè)到ServiceManager
telephonyRegistry = new TelephonyRegistry(context);
ServiceManager.addService("telephony.registry", telephonyRegistry);
//啟動(dòng)其它服務(wù)坎穿,并注冊(cè)到ServiceManager
...
//啟動(dòng)ActivityManagerService
ActivityManagerService.setSystemProcess();
//啟動(dòng)其它服務(wù)展父,并注冊(cè)到ServiceManager
...
//調(diào)用ActivityManagerService的systemReady方法,啟動(dòng)Launcher
ActivityManagerService.self().systemReady(new Runnable() {
public void run() {
...
//開始系統(tǒng)啟動(dòng)畫面
if (!headless) {
startSystemUi(contextF);
}
...
});
//不停的從消息隊(duì)列中獲取消息
Looper.loop();
}
- initAndLoop方法中玲昧,SystemServer主要負(fù)責(zé)啟動(dòng)各種服務(wù)栖茉,并將啟動(dòng)的服務(wù)注冊(cè)到ServiceManager中。
- 上方法中注意ActivityManagerService的啟動(dòng)孵延,可知:
- AMS在SystemServier進(jìn)程中運(yùn)行吕漂;
- SystemServer調(diào)用AMS的systemReady方法來啟動(dòng)系統(tǒng)UI了;
插話
上面講完SystemServer進(jìn)程創(chuàng)建后,下一部分就是應(yīng)用進(jìn)程創(chuàng)建了尘应,這部分內(nèi)容在后面文章展開惶凝,這里貼副圖簡單描述下Zygote是如何創(chuàng)建應(yīng)用進(jìn)程的。改圖以Zygote創(chuàng)建Launcher進(jìn)程為例:
總結(jié)
回顧整篇內(nèi)容犬钢,可以用下圖做個(gè)簡單描述:
本文從init進(jìn)程啟動(dòng)出發(fā)苍鲜,沿著zygote進(jìn)程、SystemServer進(jìn)程創(chuàng)建流程分析了Android系統(tǒng)啟動(dòng)玷犹,其中內(nèi)容無非是這么幾點(diǎn):
- init進(jìn)程創(chuàng)建了Zygote進(jìn)程
- Zygote進(jìn)程孵化創(chuàng)建了SystemServer進(jìn)程
- SystemServer進(jìn)程啟動(dòng)了Android常見的系統(tǒng)服務(wù)混滔,如AMS、PMS等。及SystemServer可理解為應(yīng)用與之交互的遠(yuǎn)程服務(wù)端坯屿。
- 已知Android的每個(gè)進(jìn)程都與一個(gè)VM關(guān)聯(lián)油湖,上面代碼未展開描述,但可概括為:VM由Zygote創(chuàng)建领跛,Zygote每創(chuàng)建一個(gè)進(jìn)程乏德,就為為該進(jìn)程拷貝一份VM實(shí)例,從而實(shí)現(xiàn)關(guān)聯(lián)吠昭。
在后面的兩篇文章中喊括,會(huì)從Activity啟動(dòng)角度出發(fā),分析Zygote是如何創(chuàng)建應(yīng)用進(jìn)程怎诫,以及ActivityThread有如何使主線程等問題瘾晃。