Android zygote启动流程详解
作者:kailasa 发布时间:2023-09-13 07:44:12
目录
对zygote的理解
作用
启动流程
启动入口
脚本讲解
启动过程
App_main::main
AndroidRuntime::start
对zygote的理解
在Android系统中,zygote是一个native进程,是所有应用进程的父进程。而zygote则是Linux系统用户空间的第一个进程——init进程,通过fork的方式创建并启动的。
作用
zygote进程在启动时,会创建一个Dalvik虚拟机实例,每次孵化新的应用进程时,都会将这个Dalvik虚拟机实例复制到新的应用程序进程里面,从而使得每个应用程序进程都有一个独立的Dalvik虚拟机实例。
zygote进程的主要作用有两个:
启动SystemServer。
孵化应用进程。
启动流程
启动入口
Zygote进程在init进程中,通过解析init.zygote.rc配置文件,以service(服务)的方式启动并创建的。
以init.zygote32.rc为例来看下:
脚本讲解
// system\core\rootdir\init.zygote32.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
这段脚本要求 init 进程创建一个名为 zygote 的进程,该进程要执行的程序是“/system/bin/app_process”。并且为 zygote 进程创建一个 socket 资源 (用于进程间通信,ActivityManagerService 就是通过该 socket 请求 zygote 进程 fork 一个应用程序进程)。
后面的**--zygote**是参数,表示启动的是zygote进程。在app_process的main函数中会依据该参数决定执行ZygoteInit还是Java类。
启动过程
zygote要执行的程序便是system/bin/app_process,它的源代码在frameworks/base/cmds/app_process/app_main.cpp
App_main::main
int main(int argc, char* const argv[])
{
...
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {//是否有--zygote参数。这个是启动zygote进程的时候的参数
zygote = true;
//进程名称,设置为zygote
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {//是否有--start-system-server
startSystemServer = true;
....
if (zygote) {
//最最重要方法。。。如果是zygote进程,则启动ZygoteInit。
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
AndroidRuntime::start
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
JNIEnv* env;
//重点方法 创建VM虚拟机,参数是指针,可以用于获取返回的值,可以使用env来和Java层来做交互
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
//重点方法 给虚拟机注册一些JNI函数,(系统so库、用户自定义so库 、加载函数等。)
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
//找到类的main方法,并调用。如果是zygote的话,这里就会启动ZygoteInit类的main方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
//调用main方法。这里通过JNI调用Java方法之后,Zygote(Native层)就进入了Java的世界,从而开启了Android中Java的世界。
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
App_main.main
AndroidRuntime.start
startVm//创建虚拟机
startReg//注册JNI函数
ZygoteInit.main//这里就进入到了Java层了
registerZygoteSocket//建立IPC的通讯机制
preload//预加载类和资源
startSystemServer//启动system_server
runSelectLoop//等待进程创建的请求
对应的源码地址: /frameworks/base/cmds/app_process/App_main.cpp (内含AppRuntime类) /frameworks/base/core/jni/AndroidRuntime.cpp /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java /frameworks/base/core/java/com/android/internal/os/Zygote.java /frameworks/base/core/java/android/net/LocalServerSocket.java
Zygote进程的启动过程中,除了会创建一个Dalvik虚拟机实例之外,还会将Java运行时库加载到进程中,以及注册一些Android核心类的JNI方法到创建的Dalvik虚拟机实例中。
zygote进程初始化时启动虚拟,并加载一些系统资源。这样zygote fork出子进程之后,子进程也会继承能正常工作的虚拟机和各种系统资源,剩下的只需要装载APK文件的字节码就可以运行程序,。
Java应用程序不能以本地进程的形态运行,必须在一个独立的虚拟机中运行。如果每次都重新启动虚拟机,肯定就会拖慢应用程序的启动速度。
注意:APK应用程序进程被zygote进程孵化出来以后,不仅会获得Dalvik虚拟机实例拷贝,还会与Zygote一起共享Java运行时库。
来源:https://juejin.cn/post/6944949447503642632
猜你喜欢
- VisualVM是JDK自带的一款全能型性能监控和故障分析工具,包括对CPU使用、JVM堆内存消耗、线程、类加载的实时监控,内存dump文件
- 概要应同学邀请,演示如何使用 PyQt5 内嵌浏览器浏览网页,并注入 Javascript 脚本实现自动化操作。下面测试的是一个廉价机票预订
- 本文实例为大家分享了java实现简单单链表的具体代码,供大家参考,具体内容如下一、定义:单链表是一种链式存取的数据结构,用一组地址任意的存储
- StringRedisTemplate与RedisTemplate区别点两者的关系是StringRedisTemplate继承RedisTe
- 前言嗯。最近工程上遇到一个byte数组转换为int的问题,解决过程中遇到了几个坑,经过各种查资料终于还是解决了。撒花。Java的位运算以及b
- 目录1、Stream API2、ParallelStreams执行原理3、ParallelStreams注意事项前言:并行编程势不可挡,Ja
- 前言:在没有接触java8的时候,我们遍历一个集合都是用循环的方式,从第一条数据遍历到最后一条数据,现在思考一个问题,为什么要使用循环,因为
- 三层架构将整个业务应用划分为:(1)界面UI层(2)业务逻辑层(3)数据访问层对于复杂的系统分层可以让结构更加清晰,模块更加独立,便于维护。
- 本文主要研究的是关于Java中重载,重写,多态,静态绑定、动态绑定的相关内容,具体如下。重载,英文名是overload,是指在一个类中定义了
- 一,简介Feign使得 Java HTTP 客户端编写更方便。Feign 灵感来源于Retrofit、JAXRS-2.0和WebSocket
- 先看MVC模式流程图(其实MVC设计模式就是java中的model2。): &nb
- 引言你在服务端的安全管理使用了 Spring Security,用户登录成功之后,Spring Security 帮你把用户信息保存在 Se
- 1.配置多个数据源多个数据源是指在同一个系统中,用户数据来自不同的表,在认证时,如果第一张表没有查找到用户,那就去第二张表中査询,依次类推。
- 方法调用在程序运行时,进行方法调用是最普遍,最频繁的操作方法调用不等于方法执行:方法调用阶段唯一的任务就是确定被调用的方法版本,即调用哪一个
- 关于Context我们首先应该知道:(1)它描述的是一个应用程序环境的信息,即上下文。(2)该类是一个抽象(abstract class)类
- 接口定义了一系列的行为规范,为类型定义一种Can-Do的功能。例如,实现IEnumerable接口定义了GetEnumerator方法,用于
- java ,javaw 和 javaws 的区别:首先,所有的这些都是java的启动装置,java.e
- Java中throws和throw的区别讲解当然,你需要明白异常在Java中式以一个对象来看待。并且所有系统定义的编译和运行异常都可以由系统
- 1.理解装箱简单地说,装箱就是将一个值类型的数据存储在一个引用类型的变量中。假设你一个方法中创建了一个 int 类型的本地变量,你要将这个值
- 前言本文主要跟大家介绍了关于Java用gson解析Json的相关内容,分享出来供大家参考学习,需要的朋友们下面来一起看看吧。json数据{&