先说结论:
MethodAndArgsCaller
类继承自Exception
类,并且实现了Runnable
接口。在run方法里面,通过反射,也就是Method.invoke方法,完成ActivityThread.main()方法的调用。MethodAndArgsCaller
类的对象是一个异常,被抛出后,被catch到,然后通过对象调用run方法。这样run方法,最终是在ZygoteInit的main方法里面调用的。
本文源码版本Android6.0 , SDK版本23
通过我的这篇文章:在线查看Android系统源码,可以快速查看在线源码。
在线源码链接:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
具体过程:
从ZygoteInit的main方法开始,到调用runOnce方法:
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.runOnce源码如下:
/**
* 该方法主要做了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()
* 这个Process类源码路径是:/frameworks/base/core/java/android/os/Process.java
* 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;
}
/**
* 入参parsedArgs包含了className
* 该方法实际就是调用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.zygoteInit方法:
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 {
// ...省略大段代码...
final Arguments args;
...
args = new Arguments(argv);
...
// 启动指定类的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);
}
/*
* 上面全部满足后,new了一个异常对象,throw抛出了异常,
* 这个异常在文章开头ZygoteInit.main()中被捕获,
* 就是上面提示要注意的地方,在异常捕获的地方执行caller.run()方法;
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
继续看看类:MethodAndArgsCaller
,MethodAndArgsCaller是ZygoteInit的一个静态内部类。
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);
}
}
}
新的问题:SystemServer是怎么读取ActivityThread.main()方法信息的?