Android程序是如何运行起来的?
文章目录
- Android程序是如何运行起来的?
- 概述
概述
要知道Android系统简单描述可以认为是Linux内核加上Java虚拟机。大部分Android程序,都是Java或者Kotlin这些JVM语言所写的。Android程序的启动过程,实际上就是Android系统启动Java虚拟机执行Java/Kotlin代码的过程。那么Android系统是怎么启动虚拟机的呢?这个问题得从Android系统启动说起。第一步当然是内核启动,Linux内核启动就是另一个非常复杂的问题了,这里先不说。Linux启动完成后呢,首先会启动第一个用户态的进程,叫做init进程,init进程是系统用户态中几乎所有进程的祖先。init进程会启动许多系统运行所需要的关键进程,这里面就包括zygote,zygote是系统里面的第一个Java进程。在zygote进程启动的过程中,会启动Java虚拟机,注册好虚拟机运行以及应用运行需要的一些JNI方法,load好一堆Java class,总之是一个很复杂的过程。然后呢,zygote进程跑起来之后,就会fork自身启动一个叫system_process的系统进程来运行framework的Java代码,然后system_process会启动一些必要的系统应用例如桌面等等。这个过程其实和启动应用程序很接近了。与此同时,zygote也开始监听其他进程发送来的启动新进程的请求。比如说我从桌面点了一个应用图标,那么桌面会请求系统启动这个图标对应的应用。这时这个应用还没有运行,那么我们需要启动一个Java虚拟机来运行这个应用的代码。这时候系统就会告诉zygote,我需要一个新Java虚拟机,zygote收到请求后,就会从自己本身,fork一个新进程出去。粗浅一点理解,fork就相当于从它自身复制了一个一模一样的进程出去,然后在新进程里面开始执行app的代码。可能有小伙伴会问,这里为什么要让zygote去复制自己而系统不直接新起一个呢?答案前面有提到,JVM的启动是一个很复杂的过程,需要注册很多JNI方法,load很多class等等,如果系统重新启动一个新的,那么这里就会很耗时。所以让zygote去复制它自身,以加快应用启动过程。这里也是zygote(受精卵)这个命名的意义所在。那么说到了新进程将会加载应用的代码去执行,这个加载执行又是另一个复杂的过程。一般来讲应用执行是有个入口函数的,通常叫main函数。我们写Android应用其实是没有自己写main函数的,那么Android应用的main函数在哪里呢?结合前面zygote启动新进程的过程,新进程应该也是加载的某一个有main函数的类,去看zygote的源码,就可以发现,zygote启动应用的时候是加载的一个叫android.app.ActivityThread的类。这个类我们平常在Android的崩溃日志,或者直接IDE里面搜索也能看得到。在ActivityThread的main方法里面,开启了应用的MainLooper,可以理解为我们平常说的应用主线程,开始无限循环处理应用的消息队列里面的消息。然后ActivityThread会与system_process交互,告诉系统自己已经准备好了,可以干活了,然后这时候系统会把之前桌面启动该应用的请求交还给它,这时候应用就会去加载请求所对应的类比如某一个activity等,去执行里面的代码。