本文涉及的内容,可也以被称为:《Android应用进程的孵化》
《源码分析 — SystemServer》一文中介绍了
SystemServer.main()
方法被触发的时机;
在ActivityThread
中也有一个main()
方法,那它是在什么时候被触发的呢?
源码版本:Android 23
涉及到的知识点:
从这张时序图来看,整个流程分为两个部分:
下面分着两部分进行源码分析;
这部分涉及到以下几个类:
ZygoteInit
ZygoteConnection
RuntimeInit
MethodArgsCaller
ActivityThread
ZygoteInit
public static void main(String argv[]) {
try {
// ...代码省略...
// 本文重点:接收命令socket连接;
runSelectLoop(abiList);
} catch (MethodAndArgsCaller caller) {
caller.run();//在启动子进程的过程中(最终还是调用到这里,执行ActivityThread.main()方法)
}
}
/**
* 从下面的注释就可以看出:
* 在process中运行一个loop,用于接收从新连接返回的指令(commands);
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*
* 最后抛出MethodAndArgsCaller异常,在此异常捕获的地方执行子process的main()方法;
* @throws MethodAndArgsCaller in a child process when a main() should
* be executed.
*/
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
// ...代码省略...
// 无限轮训
while (true) {
// ...代码省略...
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
// 最终执行这里ZygoteConnection.runOnce()方法;
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
ZygoteConnection
/**
* 该方法主要做了3件事:
* 1.读取子进程创建时,传递的参数信息;
* 2.根据这些参数,从Zygote中fork一个子进程;
* 3.对这个子进程进行处理;
*/
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
// 1.readArgumentList() 读取SystemServer发送过来的参数
String[] args = readArgumentList();
if (args == null) {
return true;
}
// ...代码省略...
Arguments parsedArgs = null;
int pid = -1;
try {
parsedArgs = new Arguments(args);
// ...代码省略...
// 2.根据参数,fork一个子进程
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
} catch (Exception ex) {
// ...
}
if (pid == 0) {
// 3.处理子进程
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
}
// ...
}
/**
* 从指令套接字中读取参数集,然后存储在一个String数组中,并返回该数组;
*
* 该方法接收来自Process.zygoteSendArgsAndGetPid()的数据,
* 数据的传输是通过Socket进行的;
*/
private String[] readArgumentList()
throws IOException {
/*
* 为什么这里s是一个Integer类型呢?
* 请查看:Process.zygoteSendArgsAndGetResult()
* s:代表参数的个数;
*/
String s = mSocketReader.readLine();
int argc = Integer.parseInt(s);
// ...
String[] result = new String[argc];
for (int i = 0; i < argc; i++) {
result[i] = mSocketReader.readLine();
if (result[i] == null) {
throw new IOException("truncated request");
}
}
return result;
}
/**
* 该方法实际就是调用了Activity.main();
*/
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
// ...代码省略...
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith, ...);
} else {
// 实际执行这里,其实到了这里已经很清晰了,执行过程跟SystemServer的启动一样;
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}
RuntimeInit
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
applicationInit(targetSdkVersion, argv, classLoader);
}
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
// ...省略大段代码...
// 启动指定类的main方法(startClass 代表要启动的类的类名)
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
/*
* 这个方法的主要作用:
* 将从Socket中获取的参数信息args,通过反射获取到即将要被调用的类的main()方法;
*/
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class> cl;
try {
// 1.根据类名获取class对象
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
// 2.声明main方法
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
// 3.校验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()中被捕获,
* 就是上面提示要注意的地方,在异常捕获的地方执行caller.run()方法;
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
MethodAndArgsCaller
public static class MethodAndArgsCaller extends Exception
implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
// mMethod就是SystemServer.main()方法;
mMethod.invoke(null, new Object[] { mArgs });
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
Zygote
进程调用 ZygoteInit.runSelectLoop()
开启一个轮训器;SystemServer
进程发送消息到 Zygote
,在 ZygoteConnection.readArgumentList()
中接收消息;Zygote
通过 fork 创建子进程;android.app.ActivityThread.main()
方法;其实,这个原理跟
Handler
的Looper
原理很像,Looper
开启一个轮训器,不断的从MessageQueue
中获取最新的Message
,进而处理这个消息;
而在ZygoteInit.runSelectLoop()
也是启动一个轮训器,从指定的Socket
中读取数据,然后进行处理;
这部分涉及到以下几个类:
LauncherActivity
ActivityManagerService
Process
LauncherActivity
// 在 LauncherActivity 中,如下代码启动了一个应用程序;
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = adapter.intentForPosition(position);
startActivity(intent);
}
小结:
startActivity(intent)
启动一个 Activity
,经过多次的跳转后,最终将执行 ActivityManagerService.startActivity()
方法;ActivityManagerService.startActivity()
方法又经过多次跳转后,执行了 ActivityManagerService.startProcessLocked()
方法; ( 请参考《源码分析 — Activity的启动流程》)ActivityManagerService
由 4.1 的小结可知,最终调用 ActivityManagerService.startProcessLocked()
方法
// 注意,这里的 entryPoint = null
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
// ......
try {
// ......
// 注意:这里设置了ActivityThread 的类名信息;
if (entryPoint == null)
entryPoint = "android.app.ActivityThread";
// 这里调用了Process.start()启动一个进程;
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
// ......
} catch (RuntimeException e) {
// ......
}
}
Process
// processClass其实就是"android.app.ActivityThread"
public static final ProcessStartResult start(final String processClass,
final String niceName, int uid, int gid, int[] gids,
int debugFlags, int mountExternal, int targetSdkVersion,
String seInfo, String abi, String instructionSet,
String appDataDir, String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
// ......
}
}
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName, final int uid, final int gid,
final int[] gids, int debugFlags, int mountExternal,
int targetSdkVersion, String seInfo, String abi,
String instructionSet, String appDataDir,
String[] extraArgs) throws ZygoteStartFailedEx {
synchronized(Process.class) {
ArrayList argsForZygote = new ArrayList();
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
// 给argsForZygote添加参数信息;
// 将processClass="android.app.ActivityThread"当做启动的参数传入argsForZygote中;
argsForZygote.add(processClass);
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
/*
* 从Zygote进程将参数信息argsForZygote通过Socket发送出去;
* openZygoteSocketIfNeeded():打开一个Zygote的Socket通道;
*/
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
/*
* 该方法做了以下几件事:
* 1.开启一个Zygote的Socket通信通道;
* 2.将启动子进程的参数写入到Socket中;
* 3.等待ZygoteInit.readArgumentList()从Socket通道中读取参数信息,并读取子进程的pid;
* 4.判断子进程的pid<0是否成立,从而判断子进程是否fork成功;
*/
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList args)
throws ZygoteStartFailedEx {
try {
/**
* 从下面这段注释可以看出,zygoteState.writer在写入时,
* ZygoteInit.readArgumentList()就能读取到相应的参数信息;
*
* See com.android.internal.os.ZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* 在Zygote进程获取到这些参数后,就会返回一个子进程的pid(进程Id);如果失败了,pid=-1;
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
/*
* 这里第一行输入的是参数的个数,所以这就是为什么在ZygoteInit.readArgumentList()方法中
* 获取到第一行数据s后,将它转换成Integer类型的原因;
*/
writer.write(Integer.toString(args.size()));
writer.newLine();
// 将参数 args 一行行写入Socket中;
int sz = args.size();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
if (arg.indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx(
"embedded newlines not allowed");
}
writer.write(arg);
writer.newLine();
}
writer.flush();
// Should there be a timeout on this?
ProcessStartResult result = new ProcessStartResult();
// 获取到新的子进程的Pid
result.pid = inputStream.readInt();
if (result.pid < 0) {// 如果pid < 0,就说明子进程fork失败;
throw new ZygoteStartFailedEx("fork() failed");
}
result.usingWrapper = inputStream.readBoolean();
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
Process.start()
中接收了需要启动的类 android.app.ActivityThread
;Process.startViaZygote()
方法中,添加启动子进程所需的参数信息;Process.zygoteSendArgsAndGetResult()
方法;