之前花过一段时间整理了下Android系统启动、Activity启动以及ActivityThread等系统内容。时间久远,很多细节都忘了,本着互联共享的精神,在这里把之前的文档重新整理。计划写三篇文章:《梦幻曲:Android系统启动》,《沉思曲:Activity启动》、《小夜曲:ActivityThread分析》,一家之言难免有各种问题,仅供参考。
参考 | http://blog.csdn.net/jeffbao/article/details/18242515
概念
Dalvik虚拟机
当java程序运行时,都是有一个虚拟机来解释java的字节码,它将这些字节码翻译成本地CPU的指令码,然后执行。
AndroidRuntime
归纳起来的意思就是,Runtime 是支撑程序运行的基础库,它是与语言绑定在一起的。比如:
- C Runtime:就是C standard lib,也就是我们常说的libc。(有意思的是, Wiki会自动将“C runtime" 重定向到 "C Standard Library")。
- Java Runtime: 同样,Wiki将其重定向到” Java Virtual Machine",这里当然包括Java 的支撑类库(.jar)。
-
AndroidRuntime: 显而易见,就是为Android应用运行所需的运行时环境。包括:
- Dalvik VM: Android的Java VM,解释运行Dex格式Java程序。每个进程运行一个虚拟机(什么叫运行虚拟机?说白了,就是一些C代码,不停的去解释Dex格式的二进制码(Bytecode),把它们转成机器码(Machine code),然后执行。
- 当然,现在大多数的Java 虚拟机都支持JIT,也就是说,byte code可能在运行前就已经被转换成机器码,从而大大提高了性能。过去一个普遍的认识是Java 程序比C,C++等静态编译的语言慢,但随着JIT的介入和发展,这个已经完全是过去时了,JIT的动态性运行允许虚拟机根据运行时环境,优化机器码的生成,在某些情况下,Java甚至可以比C/C++跑得更快,同时又兼具平台无关的特性,这也是为什么Java如今如此流行的原因之一吧)。
- Android的Java 类库, 大部分来自于 Apache Hamony, 开源的Java API 实现,如 java.lang, java.util, java.net. 但去除了AWT, Swing 等部件。
- JNI: C和Java互调的接口。
- Libc: Android也有很多C代码,自然少不了libc,注意的是,Android的libc叫 bionic C.
- Dalvik VM: Android的Java VM,解释运行Dex格式Java程序。每个进程运行一个虚拟机(什么叫运行虚拟机?说白了,就是一些C代码,不停的去解释Dex格式的二进制码(Bytecode),把它们转成机器码(Machine code),然后执行。
图
框架图
在往下讲之前,先看下框架图:
代码流程图
init进程
init进程的启动配置在init.rc文件中,
note:init.rc文件的语法可参考:init.rc分析
1.1、init进程启动ServiceManager
/*service后第一个参数为进程名,第二个参数为进程路径,后面参数为启动改进程传递的参数*/
//service关键字启动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负责管理所有的服务(native service、java service),如服务的注册、查找等。
- native service主要有: surfaceflinger、drm、media等。
- java service主要有:ActivityManagerService、WindowManagerService、PowerManagerService等。
- 其中,native service大多在init.rc文件中由service关键字创建启动;java service大多由zygote创建启动。
1.2、init进程启动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第二个参数可知,此处启动的进程为zygote进程,并由app_process实现。
- zygote由java编写,不能有init进程直接启动;必须先生成Dalvik虚拟机,再在Dalvik虚拟机中装载zygote的实现类(ZygoteInit.java)。
Zygote进程
在往下讲Zygote进程前,先看附图,了解下Zygote都做啥了:
Zygote进程的入口在app_main.cpp文件的main方法中,看下其main方法
2.1 main | app_main.cpp
int main(int argc, char* const argv[])
{
...
//解析入参,此处入参为“--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;
}
}
//设置进程名
if (niceName && *niceName) {
setArgv0(argv0, niceName);
set_process_name(niceName);
}
runtime.mParentDir = parentDir;
if (zygote) {
//start生成并初始化Dalvik虚拟机,并加载ZygoteInit类到虚拟机中
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类到虚拟机中
runtime.start("com.android.internal.os.RuntimeInit",
application ? "application" : "tool");
} else {
app_usage();
return 10;
}
}
- 入参为“--zygote --start-system-server”,通过调用runtime.start创建和生成Dalvik虚拟机,并加载ZygoteInit类到虚拟机中。
- 加载ZygoteInit类,调用其main方法,启动SystemServer。
2.2、main | ZygoteInit.java
public static void main(String argv[]) {
try {
//注册server socket
//其它进程的创建,通过连接到该Socket后,由zygote孵化
registerZygoteSocket();
...
//预加载android framework类和资源
preload();
...
if (argv[1].equals("start-system-server")) {
//启动SystemServer
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
//死循环接收client socket连接,由此创建新进程
runSelectLoop();
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
closeServerSocket();
throw ex;
}
}
- 入参为"start-system-server",Zygote进程调用 startSystemServer()方法启动SystemServer。
2.3、startSystemServer
startSystemServer方法在ZygoteInit.java中,看方法名是要启动SystemServer进程了。
private static boolean startSystemServer()
throws MethodAndArgsCaller, RuntimeException {
...
//启动systemServer的参数
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",
//启动的SystemServer全限定名,后续根据该参数反射创建实例
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
/**
* 将传入参数进行转换
* 注意:参数com.android.server.SystemServer 放在parsedArgs中的remainingArgs里
*/
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
//Zygote为SystemServer创建子进程
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
//子进程执行
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
return true;
}
- Zygote为SystemServer创建新进程,并在新进程中调用handleSystemServerProcess。
SystemServer进程
上一步中调用了handleSystemServerProcess方法。
3.1、handleSystemServerProcess
该方法在ZygoteInit.java文件中
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
//关闭SystemServer进程的serversocket
//SystemServer进程基础了父进程zygote所有资源
closeServerSocket();
//设置文件权限
Libcore.os.umask(S_IRWXG | S_IRWXO);
//设置新进程名
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);
}
}
- 新进程中接着调用RuntimeInit.zygoteInit方法
3.2、RuntimeInit.zygoteInit
RuntimeInit.zygoteInit为静态方法,在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();
//调用该方法,往下执行
applicationInit(targetSdkVersion, argv);
}
3.3、applicationInit
上方法接着调用了applicationInit方法,该方法在RuntimeInit.java文件中。
private static void applicationInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
//应用调用System.exit(),退出进程
nativeSetExitWithoutCleanup(true);
//设置堆
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;
}
//创建args.startClass实例,并调用其main方法
invokeStaticMain(args.startClass, args.startArgs);
}
- 该方法接着调用invokeStaticMain方法,注意:此处args.startClass为com.android.server.SystemServer
3.4、invokeStaticMain
上方法接着调用了invokeStaticMain方法,该方同样在RuntimeInit.java中。看方法名,似乎是反射调用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);
}
/**
* 该异常会在ZygoteInit.main()中被捕获,
* 捕获后会触发MethodAndArgsCaller的run()方法,
* run方法中完成类main方法的调用
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
- 该方法最后通过抛异常的方式,抛出异常MethodAndArgsCaller;该异常被Zygote捕获,捕获后调用该异常的run方法,而在run放中完成类main方法的调用。
- 因此,该步最后调用SystemServer的main方法。
3.5、main | SystemServer.java
终于调用SystemServer的main方法了,看下其java层代码主要干啥了。
public static void main(String[] args) {
...
//SystemServer需要一直运行,因此它需要有效的利用内存
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
Environment.setUserRequired(true);
System.loadLibrary("android_servers");
//初始化native服务
nativeInit();
//ServerThread并非Thread,它只是运行在SystemServer进程的主线程中
ServerThread thr = new ServerThread();
//调用该方法初始化和循环处理
thr.initAndLoop();
}
3.6、initAndLoop
上面方法的主要内容在initAndLoop方法中,该方法是SystemServer的内部类ServerThread的方法。
public void initAndLoop() {
...
//main looper
Looper.prepareMainLooper();
...
try {
//启动DisplayManagerService服务,并注册到ServiceManager
display = new DisplayManagerService(context, wmHandler);
ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
//启动TelephonyRegistry服务,并注册到ServiceManager
telephonyRegistry = new TelephonyRegistry(context);
ServiceManager.addService("telephony.registry", telephonyRegistry);
//启动其它服务,并注册到ServiceManager
...
//启动ActivityManagerService
ActivityManagerService.setSystemProcess();
//启动其它服务,并注册到ServiceManager
...
//调用ActivityManagerService的systemReady方法,启动Launcher
ActivityManagerService.self().systemReady(new Runnable() {
public void run() {
...
//开始系统启动画面
if (!headless) {
startSystemUi(contextF);
}
...
});
//不停的从消息队列中获取消息
Looper.loop();
}
- initAndLoop方法中,SystemServer主要负责启动各种服务,并将启动的服务注册到ServiceManager中。
- 上方法中注意ActivityManagerService的启动,可知:
- AMS在SystemServier进程中运行;
- SystemServer调用AMS的systemReady方法来启动系统UI了;
插话
上面讲完SystemServer进程创建后,下一部分就是应用进程创建了,这部分内容在后面文章展开,这里贴副图简单描述下Zygote是如何创建应用进程的。改图以Zygote创建Launcher进程为例:
总结
回顾整篇内容,可以用下图做个简单描述:
本文从init进程启动出发,沿着zygote进程、SystemServer进程创建流程分析了Android系统启动,其中内容无非是这么几点:
- init进程创建了Zygote进程
- Zygote进程孵化创建了SystemServer进程
- SystemServer进程启动了Android常见的系统服务,如AMS、PMS等。及SystemServer可理解为应用与之交互的远程服务端。
- 已知Android的每个进程都与一个VM关联,上面代码未展开描述,但可概括为:VM由Zygote创建,Zygote每创建一个进程,就为为该进程拷贝一份VM实例,从而实现关联。
在后面的两篇文章中,会从Activity启动角度出发,分析Zygote是如何创建应用进程,以及ActivityThread有如何使主线程等问题。