Zygote在Framework中起什么作用?
创始人
2024-03-17 08:20:53

前言

提到Zygote可能了解一些的小伙伴会说,它是分裂进程用的。没错它最大的作用的确是分裂进程,但是它除了分裂进程外还做了什么呢。还是老规矩,让我们抱着几个问题来看文章。最后在结尾,再对问题进行思考回复。

  1. 你能大概描述一遍Zygote的启动流程吗
  2. 我们为什么可以执行java代码,和zygote有什么关系
  3. Zygote到底都做了哪些事情

另外,我最近也看了一些写底层的文章。要么就是言简意赅到只知道Zygote的作用,但是完全不知道如何实现的,就像是背作文一样。要么是全篇都是代码,又臭又长,让人完全没有看下去的动力。

不过作为一个读者,太长的我可能完全不想看,太短的又真的完全就是被课文一点都不明白原理。

因此,本篇文章,仍旧会引入一些代码,方便大家通过代码方便记忆。但是又会将代码进行精简,以免给大家造成过度疲劳。我们的目的都是希望用最少的时间,能掌握更多的知识。

读源码时:不要过于纠结细节,不要过于纠结细节,不要过于纠结细节!重要的事情说三遍!!!

OK,让我们进入正题瞅瞅Zygote到底是个什么东西。


1.C++还是Java

选这个当标题当然是有原因的。我们知道的是Android系统启动的时候,运行的是Linux内核,执行的是C++代码。这是一个很有趣的事情。

因为我们在写App的时候,AndroidStudio默认给我们创建的都是Activity.java,而选择的语言,要么是Java要么就是Kotlin。

启动时候运行的是C++代码,应用层却可以使用Java代码,这到底是为什么呢?其实这就是Zygote的功劳之一。

2.Native层

Init进程创建Zygote时,会调用app_main.c的main() 方法。此时它依旧运行的是C++代码。我们通过下面的代码,来看下它到底做了什么。

这里它做的最关键的一件事就是启动AndroidRuntime(Android运行时)。,另外这里需要注意的是 start方法 中的 “com.android.internal.os.ZygoteInit” 这个类似于全类名。他到底是做什么的?别着急,大概2分钟后,你可能就会得到答案。

Zygote的新手村:app_main.cpp

int main(int argc, char* const argv[])
{//  创建Android运行时对象AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));// 代码省略...// 调用AppRuntime.start方法,// 而AppRuntime是AndroidRuntime的子类,并且没有重写start方法// 因此调用的是AndroidRuntime的start方法runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}

精简后的代码告诉我们,这里一共就做了两件事,第一件创建AppRuntime,第二件调用start方法。

不过,AppRuntime是AndroidRuntime的子类,他没有重写start方法,因此这里调用的是 AndroidRuntime的start() 方法。

奇迹的诞生地:AndroidRuntime
这里我依旧只保留关键代码,源码关键注释也进行了保留。由下方代码看出这里做了三件改变命运的事情。

1.startVM – 启动Java虚拟机
2.startReg – 注册JNI
3.通过JNI调用Java方法,执行com.android.internal.os.ZygoteInit 的 main 方法

/** Start the Android runtime. */
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{/* start the virtual machine */JNIEnv* env;if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {return;}/** Register android functions.*/if (startReg(env) < 0) {ALOGE("Unable to register all android natives\n");return;}/** Start VM.  This thread becomes the main thread of the VM, and will* not return until the VM exits.*/jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");env->CallStaticVoidMethod(startClass, startMeth, strArray);}
}

有了JVM,注册了JNI,我们就可以执行Java代码了。

这里我个人建议不要过于纠结细节,比如JVM是如何创建的,JNI是如何注册的。如果感兴趣的童鞋,可以下载源码,到app_main.cpp里进行查看。这里就不进行赘述了。否则代码量太大,适得其反。

3.Java层

命运的十字路口:ZygoteInit.java:

之所以说是命运的十字路口,因为Zygote会在这里创建SystemServer,但是二者却走向了截然不同的道路。

从这里就开始执行Java代码了,当然这些Java代码是运行在JVM中的。

让我们通过代码来看一下,到底都做了些什么。
class ZygoteInit{

class ZygoteInit{/*** This is the entry point for a Zygote process.  It creates the Zygote server, loads resources,* and handles other tasks related to preparing the process for forking into applications.* This process is started with a nice value of -20 (highest priority).  */// 上面是源码中的注释,小伙伴们可以自行翻译一下。// 创建了ZygoteServer,加载资源,并且介绍了这个进程的优先级是最高的-20.public static void main(String argv[]) {ZygoteServer zygoteServer = null;// 1. 预加载资源,常用的:resource,class,library等在此处进行加载preload(bootTimingsTraceLog);// 2. 创建ZygoteServer,实际是一个Socket用来进行跨进程间通信用的。zygoteServer = new ZygoteServer(isPrimaryZygote);// 3. fork出SystemServer进程,这个进程会创建AMS,ATMS,WMS,电池服务等一切只有你想不到没有它做不到的服务forkSystemServer(abiList, zygoteSocketName, zygoteServer);// 4.里面是一个while(true)循环,等待接收AMS创建进程的消息,类似于handler中的Looper.loop()zygoteServer.runSelectLoop(abiList);}
}

上面代码里的注释基本说明了ZygoteInit都干了啥。下面会再稍微总结下:

  1. 创建了ZygoteServer:这是一个Socket相关的服务,目的是进行跨进程通信。
  2. 预加载preload:预加载相关的资源,
  3. 创建SystemServer进程:通过forkSystemServer分裂除了两个进程,一个Zygote进程,一个SystemServer进程。而且由于是分裂的,所以新分裂出来的进程也拥有虚拟机,也能调用JNI,也拥有预加载的资源,也会执行后续的代码。
  4. 执行runSelectLoop():内部是一个while(true)循环,等待AMS创建新的进程的消息。(想想Looper.loop())

4. 戛然而止

没错就是这么突然,Zygote的故事到这就结束了。至于它是如何创建SystemServer,如何去创建App那就是后面的故事了。所以你还记得我的问题嘛?我替你总结一下Zygote到底做了什么:

1.创建虚拟机
2.注册JNI
3.回调Java方法ZygoteInit.java 的main方法,从这儿开始运行Java代码
4.创建ZygoteServer,内部包含Socket用于跨进程通信
5.预加载class,resource,library等相关资源
6.fork 出了 SystemServer进程。他俩除了返回的pid不同,剩下一模一样。通过返回值不同来决定剩下的代码如何运行。这个留待后续进行讲解。
7.进入while(true)循环等待,等待AMS创建进程的消息(类似于Looper.loop())

5. 多说一句

这个系列才刚刚进行到第二章,我尽量让文章不是特别长的情况下,既有代码整理思路,又有总结方便记忆。代码是源码中摘抄的,省略了很大一部分,只能保证执行顺序。有兴趣的小伙伴可以下载源码进行查看。

其实最近我看了很多文章和视频,最后却选择写文章来对知识进行总结。归根结底就是因为一句话,好记性不如烂笔头。要是真的想快速记住,真的需要亲自查看一下源码。翻源码的同时,也是在不知不觉中锻炼你阅读源码的能力。 万一以后让你学习一个新的库,你也知道大概该怎么看。

都已经到这儿了,就稍微厚个脸皮,希望各位看官,能够点个赞,加个关注。毕竟一篇文章可能就要耗费几个小时的时间,上一篇文章就几个赞,感谢这几个小伙伴,让我有继续写下去的动力。 真心感谢你们。

另外,文章中有哪里出错,请及时指出。毕竟各位才是真正的大佬。希望各位Androider,可以一起取暖,度过这个互联网寒冬!加油各位!!!

6. Zygote功能图


根据上面简易的讲解了Zygote 进程,想问下大家对Framework 这块其他的知识点了解多少?为了帮助到大家更好的深入的料及Framework 底层知识点,小编整理了份Framework 核心知识点汇总手册,里面内容不仅有Binder,还有Handler、AMS、WMS、PMS等Framework底层内容的解析:https://0a.fit/acnLL

Framework 学习手册

1.Handler机制实现原理
2.Binder原理
3.Zygote部分
4.AMS源码分析
5.深入PMS源码
6.WMS

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...