【读书笔记】Android(安卓)应用程序进程的启动过程
16lz
2021-01-26
这是罗升阳《Android 系统源代码》一书中第12章,Android 应用程序进程的启动过程,的摘要;
当 ActivityMangerService 启动一个应用程序组件时,如果发现这个组件所需要的进程没有启动,就会请求 Zygote 启动新的进程。Zygote 通过复制自身的方式创建一个新的进程,同时也会获取一个虚拟机实例;
应用程序进程启动过程中,除了获得一个虚拟机实例外,还获得一个 Binder 线程池和一个消息循环。
一、应用程序进程创建的过程
当 ActivityManagerService 创建一个新的进程是,会调用 ActivityManagerService.startProcessLocked 方法向 Zygote 发送一个创建进程请求;
Zygote.forkAndSpecialize(...) 通过调用native 方法 nativeForkAndSpecialize(...) ,fork 一个新的进程;
ZygoteConnection.handleChildProc(...) 启动新的进程;
二、消息循环的创建过程
一个新的应用进程创建完成之后,就会调用 RuntimeInit 类的静态成员函数 invokeStaticMain 将 ActivityThread 类的静态成员函数 main 设置为新创建的应用程序进程入口。 ActivityThread 类的静态成员函数 main 在调用的过程中,就会在当前应用程序进程中创建一个消息循环。Z ygoteInit.invokeStaticMain 方法
static void invokeStaticMain(ClassLoader loader, String className, String[] argv) throws ZygoteInit.MethodAndArgsCaller { Class<?> cl; try { cl = loader.loadClass(className); } catch (ClassNotFoundException ex) { throw new RuntimeException("Missing class when invoking static main " + className, ex); } Method m; try { // 通过反射进入获取ActivityThread 类的 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); } int modifiers = m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { throw new RuntimeException("Main method is not public and static on " + className); } /* * This throw gets caught in ZygoteInit.main(), which responds * by invoking the exception's run() method. This arrangement * clears up all the stack frames that were required in setting * up the process. */ // 抛出 caller 异常,在 ZygoteInit 的 main 方法里捕获 throw new ZygoteInit.MethodAndArgsCaller(m, argv); }
在ZygoteInit.main 方法中捕获 caller 异常
public static void main(String argv[]) { ····· } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { ··· } }
调用 MethodAndArgsCaller.run 方法
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 { // 调用 ActivityThread 类的 main 方法 mMethod.invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { ··· } }}
ActivityThread.main 方法里面开启消息循环
public static void main(String[] args) { ··· Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); ·· Looper.loop(); ··· }
使用抛出异常的方式进入 ActivityThread 的 main 方法的原因: ActivityMangerService 请求 Zygote 进程创建的应用程序的入口函数为 ActivityThread 类的 main 函数。但是由于新创建的应用程序 进程一开始就需要在内部初始化运行时库,以及启动 Binder 线程池,因此,当 ActivityThread 类的静态成员函数 main 被调用时,新 创建的应用程序进程实际上已经执行了相当多的代码。为了使得新创建的应用程序进程觉得它的入口函数就是 ActivityThread 类的 main ,系统就不可以在 ZygoteInit.invokeStaticMain 中直接调用。而是先抛出一个异常回到 ZygoteInit 类的 main 中,然后间接调用它,这样 巧妙利用 Java 语言的异常处理机制清理它前面的调用栈。
更多相关文章
- Android(安卓)AIDL介绍
- WebView用法与JS交互
- Android(安卓)进程间通信的方式
- Android系统启动流程简析
- 从零开始--系统深入学习android(已完成部分的目录--带链接)
- 关于Android多进程
- AIDL和远程Service调用
- 基于Google Android(安卓)操作系统的机顶盒
- [置顶] 介绍下什么是android呢?