【读书笔记】Android 应用程序进程的启动过程

来源:互联网 发布:淘宝优惠券jp519 编辑:程序博客网 时间:2024/06/10 09:28

这是罗升阳《Android 系统源代码》一书中第12章,Android 应用程序进程的启动过程,的摘要;


当 ActivityMangerService 启动一个应用程序组件时,如果发现这个组件所需要的进程没有启动,就会请求 Zygote  启动新的进程。Zygote 通过复制自身的方式创建一个新的进程,同时也会获取一个虚拟机实例;

应用程序进程启动过程中,除了获得一个虚拟机实例外,还获得一个 Binder 线程池和一个消息循环。


一、应用程序进程创建的过程

当 ActivityManagerService 创建一个新的进程是,会调用 ActivityManagerService.startProcessLocked 方法向 Zygote 发送一个创建进程请求;


Zygote.forkAndSpecialize(...) 通过调用native 方法 nativeForkAndSpecialize(...) ,fork 一个新的进程;

ZygoteConnection.handleChildProc(...) 启动新的进程;



二、消息循环的创建过程

一个新的应用进程创建完成之后,就会调用 RuntimeInit 类的静态成员函数 invokeStaticMain 将 ActivityThread 类的静态成员函数 main 设置为新创建的应用程序进程入口。 ActivityThread 类的静态成员函数 main 在调用的过程中,就会在当前应用程序进程中创建一个消息循环。




ZygoteInit.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 语言的异常处理机制清理它前面的调用栈。

0 0
原创粉丝点击