Android 进阶解密读书笔记2
启动应用程序进程
应用程序即是桌面上展示的 App,应用程序进程的启动大致逻辑是 AMS( Activity Manager Service)发起启动应用进程请求,Zygote 进程在接收到请求后 fork 应用进程(这期间会创建 Binder 线程池,消息循环)。来看看具体过程。
发起请求
在 AMS 中通过调用 startProcessLocked 方法作为 AMS 里的第一步,在这里会定义一个 entryPoint 即将要启动的应用进程入口点,android.app.ActivityThread。接着会调用 Process 类的 start 方法,该方法又去调了 ZygoteProcess 对象的 start 方法。
Process 类是用于管理系统进程的一个工具类,ZygoteProcess 并不是代表 Zygote 进程,而是持有着与 Zygote 进程通信状态的一个状态类,正是通过它才能和 Zygote 进程的 Socket 端口进行通信并发起新进程的创建的。
在 ZygoteProcess 中又调用了 startViaZygote 方法,准备了一些参数,来看下代码最后一句是关键,
synchronized(mLock) {
//openZygoteSocketIfNeeded 方法的作用就是
//1.建立与 Zygote 进程的 socket 通信,
//2.匹配合适的 ABI,如果匹配不上就会抛异常,那自然我想应用进程也就会创建失败了。
//假设方法执行成功,那么与 Zygote 进程的通信就完成了,即 Zygote 进程收到了 AMS 启动应用进程的请求,接下去就要看 Zygote 了。
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
接收请求并相应
在启动系统的时候,Zygote 进程已经创建好了 Server Socket,并监听着 AMS 的请求。如果不了解的可以看下 Android 进阶解密读书笔记1 。
此时 AMS 发来的请求就会触发 ZygoteInit 的 main 方法中 zygoteServer.runSelectLoop(abiList) 代码执行,再往里执行,会调用 ZygoteConnection 对象的 ProcessOneCommand 方法(我看的代码版本是 28,此时和书本中的方法名略有不同,但思路是一样的)。
在方法里会再去调 Zygote 的 forkAndSpecialize 方法,该方法注释说 Forks a new VM instance,也就是说应用程序进程即是一个虚拟机实例。创建成功后,会接着往下调用 ZygoteConnection 对象的 handleChildProc 方法,通过前面 AMS 发起请求时调用 startViaZygote 方法时的参数所知,isZygote 的值就是 startChildZygote 的值,是 false,所以接下去会调用 ZygoteInit 的 zygoteInit 方法。
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
//省略...
//这步调了 native 方法,为的是创建 Binder 线程池
ZygoteInit.nativeZygoteInit();
//这步会通过反射的方式找到 ActivityThread 的 main 方法,这个就是前面请求时传入的入口点,
//并返回 MethodAndArgsCaller,最终回到 ZygoteInit 的 main 方法,调用 MethodAndArgsCaller 的 run 方法,
//此时就进入了应用进程,并调用 ActivityThread 的 main 方法。
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
调用 applicationInit 方法的大致内容(基于 API 28)
protected static Runnable applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
//省略...
return findStaticMain(args.staticClass, args.startArgs, classLoader);
}
protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) {
//省略...,主要就是前面说的反射过程
//这里和书中的不同是,书中是以抛异常的形式,而到了这个版本,MethodAndArgsCaller 实现了 Runnable 接口,
//自然就不再通过异常的形式返回了,不过这样还会不会清除那些用于启动该进程而做的设置操作栈帧,我就不知道了,
//看代码注释还留着以前的注释,可能这个就不太重要了,或者大概率是我没看懂。
return new MethodAndArgsCaller(m, argv);
}
//ZygoteInit
public static void main(String argv[]) {
//省略...
final Runnable caller;
try {
//省略...
caller = zygoterServer.runSelectLoop(abiList);
} catch(Throwable ex) {
//省略...
} finally {
zygoteServer.closeServerSocket();
}
//We're in the child process and have exited the select loop. Proceed to execute the
//command.
if (caller != null) {
//这里就会去调用 ActivityThread 的 main 方法了
caller.run();
}
}
启动完毕
在执行 ActivityThread 的 main 方法时,此时就进入了应用程序进程,并且 ActivityThread 作为应用进程的主线程也会在此创建。另外 main 方法做的工作就是创建主线程的消息循环。