系统启动过程
启动Zygote进程:
启动过程开始于Zygote进程,当启动一个应用时,Zygote进程会被复用以创建新的应用进程。
这里是ZygoteInit.main的主要作用,它是Zygote进程的入口:
public class ZygoteInit {
public static void main(String argv[]) {
// ... 省略的一些前期初始化代码
// 启动系统服务进程
if (startSystemServer) {
startSystemServer(forkedProcesses);
}
// 进入Zygote的主循环
Runnable caller;
try {
caller = zygoteServer.runSelectLoop();
} catch (Throwable ex) {
// ... 处理异常
}
// 运行子进程初始化代码
if (caller != null) {
caller.run();
}
}
}
1、Zygote连接处理:
Zygote进程在初始化后会进入一个循环,等待来自ActivityManagerService(AMS)的进程启动请求。这是在runSelectLoop中处理的。
ZygoteServer.runSelectLoop 在后台等待连接请求:
public class ZygoteServer {
Runnable runSelectLoop() {
while (true) {
// 等待AMS连接
ZygoteConnection connection = acceptCommandPeer();
return connection.processOneCommand(); // 这里实际上是处理一个命令
}
}
}
2、处理启动命令:
在接收到启动请求后,ZygoteConnection.processOneCommand 方法负责处理实际启动参数。
public class ZygoteConnection {
Runnable processOneCommand() {
// 解析启动参数
Arguments args = readArgumentList();
// 调用Zygote来fork新进程
Zygote.forkAndSpecialize(...);
if (pid == 0) {
// 子进程执行到这里
return handleChildProc(args, descriptors, childPipeFd, newStderr);
} else {
// 父进程(Zygote进程)执行到这里
...
}
}
}
这 就是说,handleChildProc 方法在子进程中被调用,这里新启动的进程会完成初始化:
3. handleChildProc
handleChildProc 负责处理子进程的初始化。
public class ZygoteConnection {
private Runnable handleChildProc(Arguments parsedArgs) {
// 初始化子进程
return RuntimeInit.wrapperInit(parsedArgs);
}
}
4. RuntimeInit.wrapperInit
RuntimeInit.wrapperInit 是实际启动应用进程的方法。
public class RuntimeInit {
public static Runnable wrapperInit(Arguments args) {
return applicationInit(args);
}
private static Runnable applicationInit(Arguments args) {
return invokeStaticMain(args.startClass, args.startArgs, null);
}
protected static Runnable invokeStaticMain(String className, String[] argv, ClassLoader classLoader) {
// 反射调用main方法
Class<?> cl;
try {
cl = Class.forName(className);
Method m = cl.getMethod("main", new Class[] { String[].class });
m.invoke(null, new Object[]{argv});
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return null;
}
}
5. ActivityThread.main
以上步骤最终会调用到ActivityThread.main方法,这是实际应用进程的入口。
public class ActivityThread {
public static void main(String[] args) {
// 主线程初始化
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
Looper.loop();
}
}
总结
整个调用链从Zygote接收启动参数到涉及到的主要过程如下:
ZygoteInit.main: 启动进程,并进入等待循环。
ZygoteServer.runSelectLoop: 等待并处理启动请求。
ZygoteConnection.processOneCommand: 解析并fork新的进程。
RuntimeInit.wrapperInit: 完成子进程进一步初始化。
RuntimeInit.applicationInit: 通过反射调用指定类的main方法。
ActivityThread.main: 启动应用主线程。
接下来看看AMS是怎么传输Socket数据给Zygote的
在ActivityManagerService(AMS)中,有关启动应用进程并通过Socket请求发送给Zygote的部分,主要是通过startProcessLocked方法来实现。这个方法会调用Process.start方法,并通过Zygote发送启动请求。在启动参数中传递了android.app.ActivityThread。
具体的流程如下:
1. ActivityManagerService.startProcessLocked
ActivityManagerService的startProcessLocked方法负责启动新进程:
public class ActivityManagerService {
private boolean startProcessLocked(ProcessRecord app, ...) {
...
// 调用Process.start来启动进程
Process.ProcessStartResult startResult = Process.start(
"android.app.ActivityThread", // 这里指定类名
app.processName, ...);
...
}
}
2. Process.start
Process.start方法负责创建并启动一个新的应用进程:
public class Process {
public static ProcessStartResult start(
String processClass, // 这里是传入的 "android.app.ActivityThread"
String niceName,
...
) {
...
try {
return startViaZygote(processClass, niceName, ...);
} catch (RuntimeException e) {
...
}
}
private static ProcessStartResult startViaZygote(
String processClass,
String niceName,
...
) {
...
// 创建启动参数列表
ArrayList<String> argsForZygote = new ArrayList<String>();
// 传递启动组件类名
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
argsForZygote.add("-classpath");
argsForZygote.add("--nice-name=" + niceName);
argsForZygote.add(processClass); // 传入的类名
// 调用Zygote来启动进程
ProcessStartResult result = ZygoteProcess.zygoteSendArgsAndGetResult(
openZygoteSocketIfNeeded(abi), argsForZygote);
...
return result;
}
}
3. ZygoteProcess.zygoteSendArgsAndGetResult
这个方法通过Socket将启动参数发送给Zygote进程:
public class ZygoteProcess {
public Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
// 获取Zygote进程的Socket连接
DataOutputStream zygoteWriter = zygoteState.mZygoteOutputWriter;
// 发送启动参数
for (String arg : args) {
zygoteWriter.writeBytes(arg + "\n");
}
// 获取启动结果
ProcessStartResult result = new ProcessStartResult();
result.pid = zygoteState.mZygoteInputStream.readInt();
...
return result;
} catch (IOException ex) {
throw new ZygoteStartFailedEx(ex);
}
}
}
传递给Zygote的参数
从上述代码可以看到,Process.start方法最终构建了一个参数列表argsForZygote,其中包括要启动的类名android.app.ActivityThread,并通过ZygoteProcess.zygoteSendArgsAndGetResult发送到Zygote进程。
4. 接受请求并启动进程的Zygote代码
回到之前的细节:
ZygoteServer.runSelectLoop
Zygote进程在启动后,会进入一个循环等待AMS的请求:
public class ZygoteServer {
Runnable runSelectLoop() {
while (true) {
ZygoteConnection connection = acceptCommandPeer();
return connection.processOneCommand();
}
}
}
ZygoteConnection.processOneCommand
在接受到启动请求后,Zygote进程通过processOneCommand方法处理请求:
public class ZygoteConnection {
Runnable processOneCommand() {
// 读取并解析参数
Arguments args = readArgumentList();
// Fork新的进程
int pid = Zygote.forkAndSpecialize(args);
if (pid == 0) {
// 子进程处理
return handleChildProc(args);
} else {
// 父进程处理
...
}
}
}
总结
总结来说,关于传递类名android.app.ActivityThread的调用链如下:
ActivityManagerService.startProcessLocked: 调用Process.start方法,传入类名android.app.ActivityThread。
Process.start: 调用startViaZygote,构建参数列表并调用ZygoteProcess.zygoteSendArgsAndGetResult。
ZygoteProcess.zygoteSendArgsAndGetResult: 通过Socket将启动参数发给Zygote进程。
ZygoteServer.runSelectLoop: 接受并处理启动请求。
ZygoteConnection.processOneCommand: 解析启动参数并fork新进程。
handleChildProc: 初始化新进程,最终调用RuntimeInit.zygoteInit,并反射调用ActivityThread.main。