android 技术梳理

Android 进阶解密读书笔记2

2021-01-21  本文已影响0人  jkwen

启动应用程序进程

应用程序即是桌面上展示的 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 方法做的工作就是创建主线程的消息循环。

上一篇下一篇

猜你喜欢

热点阅读