模拟Android系统Zygote启动流程

版权声明:本文为梦想全栈程序猿原创文章,转载请附上原文出处链接和本声明

前言:

        转眼时间过去了10年了,回顾整个10年的工作历程,做了3年的手机,4年左右的Android指纹相关的工作,3年左右的跟传感器相关的工作,其实,我个人还是想了解Android底层的相关知识,目前对于啥都了解一点,都不太深入的,让我很焦虑,记录自己学习的相关知识,这个系列的文章思路是抽丝剥茧,记录Android相关知识的关键部分,目前是从Android8.0开始。

一.前置学习:了解Android的启动流程

文笔不好,只是记录下来给自己回顾,或者分享给志同道合的人一起交流跟学习;学习本文章,你需要了解Android基本的启动流程,在这里不讲,需要自行去查看相关的资料

二.Android如何进入Zygote的java代码

这个是Framework的模拟相关代码,基本上是一比一还原

通过相关Android启动流程的相关知识,可以清楚知道,系统在执行执行并解析init.rc的过程中,启动了路径为/system/bin/app_process的可执行文件;我们知道,在Linux中,死的可执行文件称为程序,活的可执行文件称为进程;可执行文件的程序入口是main函数(这个不是很严谨)

app_process.cpp文件

int main(int argc, char* const argv[])
{char* argBlockStart = "test";size_t argBlockLength = 5;AppRuntime runtime(argBlockStart, argBlockLength);runtime.start("com.huahua.moon.android.ZygoteInit", true);return 0;
}

所以根据目前的main函数,需要去看下runtime.start方法,下面是app_process.cpp的整个文件内容

#include "AndroidRuntime.h"#include <stdlib.h>#include <stdio.h>
#include <unistd.h>class AppRuntime : public AndroidRuntime
{
public:AppRuntime(char* argBlockStart, size_t argBlockLength): AndroidRuntime(argBlockStart, argBlockLength){}};int main(int argc, char* const argv[])
{char* argBlockStart = "test";size_t argBlockLength = 5;AppRuntime runtime(argBlockStart, argBlockLength);runtime.start("com.huahua.moon.android.ZygoteInit", true);return 0;
}

可以看到,runtime是AppRuntime类的对象,这个类继承自AndroidRuntime类,AppRuntime类中没有看到start函数的相关声明跟定义,所以,这个肯定是在其父类AndroidRuntime中声明跟定义的所以需要看AppRuntime跟AndroidRuntime相关的类;

这个是AndroidRuntime.h文件

#include <stddef.h>
#include <stdlib.h>#include <jni.h>#include <vector>using namespace std;
using std::vector;class AndroidRuntime
{
public:AndroidRuntime(char* argBlockStart, size_t argBlockSize);virtual ~AndroidRuntime();void addOption(const char* optionString, void* extra_info = NULL);void start(const char* className, bool zygote);void exit(int mode);static AndroidRuntime* getRuntime();static char* toSlashClassName(const char* className);private:int startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote);vector<JavaVMOption> mOptions;char* const mArgBlockStart;const size_t mArgBlockLength;static JavaVM* mJavaVM;
};

这个是AndroidRuntime.cpp部分文件

void AndroidRuntime::start(const char* className, bool zygote)
{printf("AndroidRuntime start className = %s, zygote = %d \n", className, zygote);JNIEnv* env;if (startVm(&mJavaVM, &env, zygote) != 0){return;}jstring classNameStr = env->NewStringUTF(className);char* slashClassName = toSlashClassName(className);printf("JavaVM slashClassName '%s'\n", slashClassName);jclass startClass = env->FindClass(slashClassName);if (startClass == NULL){printf("JavaVM unable to locate class '%s'\n", slashClassName);}else{jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");if (startMeth != NULL){jobjectArray strArray;env->CallStaticVoidMethod(startClass, startMeth, strArray);}}
}

所以上面app_process.cpp的main函数中,最终调用的是AndroidRuntime.cpp中的start函数,传递的参数className = ("com.huahua.moon.android.ZygoteInit"  zygote = true;因为我这篇文章是模拟,只是概述关键点,所有有其他的很多东西没有提及到;这里跟我上一次的文章是有联系的,具体也可以参考我上篇博客linux运行可执行文件,通过c语言调用java的main方法

上面的代码,主要是一下几点:

  • 启动JVM虚拟机
  • 转换class Name的格式
  • 找到对应的class
  • 获取对应class的main函数
  • 执行main函数

这里有一个细节,就是我们传递的进来的class名是"com.huahua.moon.android.ZygoteInit",这个名字是不符合JAVA相关的JNI规范的,需要修改成"com/huahua/moon/android/ZygoteInit"这种名字

startVm函数是启动java虚拟机

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{JavaVMInitArgs initArgs;#if 0addOption("-Djava.class.path=.");initArgs.version = JNI_VERSION_1_4;//initArgs.options = mOptions.editArray();//initArgs.nOptions = mOptions.size();initArgs.ignoreUnrecognized = JNI_FALSE;
#endifJavaVMOption options[1];options[0].optionString = "-Djava.class.path=.";initArgs.version = JNI_VERSION_1_4;initArgs.nOptions = 1;initArgs.options = options;if (JNI_CreateJavaVM(pJavaVM, (void **)pEnv, &initArgs) < 0){printf("JNI_CreateJavaVM failed \n");return -1;}else{printf("JNI_CreateJavaVM create success  \n");}return 0;
}

toSlashClassName函数是把"com.huahua.moon.android.ZygoteInit"转化成"com/huahua/moon/android/ZygoteInit"这种格式

char* AndroidRuntime::toSlashClassName(const char* className)
{char* result = strdup(className);for (char* cp = result; *cp != '\0'; cp++) {if (*cp == '.') {*cp = '/';}}return result;
}

三.模拟结果

通过执行app_process 可执行文件, 输出了java 代码的main函数中的系统输出,证明了Android 进入了Zygote的java代码

ZygoteInit.java 的代码如下图所示

三.注意问题

模拟代码是一个稍微完整的工程代码,本篇文章只是包含了其中的一部分

四.如何编译测试

1.用本工程的java代码编译出class文件,使用java命令或者intellij idea 工具编译都行

2.使用本工程的cpp部分代码,编译出app_process 可执行文件,目前本工程的构建工具是Cmake

3.拷贝到out目前, 请注意目录结构

五.思考问题

真的只有面向对象语言有封装的特性吗? 

此工程中的cpp代码从封装性,跟C语言的代码对比而言.(ps:在这个头文件中竟然能看到类的相关私有数据成员)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/817041.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

亚马逊CloudFront使用体验

前言 首先在体验CloudFront之前&#xff0c;先介绍一下什么是CDN&#xff0c;以及CDN的基本原理。 CDN是Content Delivery Network&#xff08;内容分发网络&#xff09;的缩写&#xff0c;是一种利用分布式节点技术&#xff0c;在全球部署服务器&#xff0c;即时地将网站、应…

《由浅入深学习SAP财务》:第2章 总账模块 - 2.6 定期处理 - 2.6.6 年初操作:科目余额结转

2.6.6 年初操作&#xff1a;科目余额结转 在使用事务代码 FAGLB03 查询科目余额时&#xff0c;可以看到按期间的发生额清单。其中&#xff0c;第一行称为“余额结转”&#xff0c;该行的累计余额代表上年度遗留下来的余额&#xff0c;也就是年初余额。对于资产负债表科目而言&a…

七大设计原则

在软件开发的领域中&#xff0c;随着技术的不断进步和市场需求的不断变化&#xff0c;软件系统的设计和维护变得越来越重要。为了确保软件系统能够长期有效地运行&#xff0c;并且能够在未来的发展中适应新的需求和技术变化&#xff0c;提高软件系统的可维护性和可复用性成为了…

map与set

set使用 set在我们就是我们前面学习的k模型&#xff0c;它可以用来比对数据&#xff0c;增删查的时间复杂度都是O&#xff08;logn&#xff09;效率非常高&#xff0c;由于它底层的原因&#xff0c;它也可以实现排序&#xff0c;通过中序遍历可以输出我们的有序的数据&#xff…

安装gensim报错

安装gensim pip install --upgrade gensim装完以后注意一个 装了一堆库其实&#xff0c;看下对应的scipy版本是1.13.0 然后运行 import gensim报错&#xff1a; cannot import name ‘triu’ from ‘scipy.linalg’ https://www.soinside.com/question/brZ46N5EH7bk9xdVwXa…

华为OD机试 - 内存冷热标记(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

Springboot+Vue项目-基于Java+MySQL的高校心理教育辅导系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

【Linux网络编程】TCP协议

TCP协议 1.TCP协议段格式4位首位长度序号和确认序号16位窗口大小6个标志位 2.确认应答机制3.超时重传机制4.连接管理机制如何理解连接如何理解三次握手如何理解四次挥手 5.流量控制6.滑动窗口7.拥塞控制8.延迟应答9.捎带应答10.面向字节流11.粘包问题12.TCP异常情况13.TCP小结1…

亚马逊全球跨境市场地位稳固,武汉星起航深化服务助力合作伙伴

在全球跨境电商市场的激烈竞争中&#xff0c;亚马逊凭借其强大的市场地位和卓越的平台特点&#xff0c;持续引领着行业的发展潮流。作为行业的领军者&#xff0c;亚马逊不仅占据了全球市场的一大部分&#xff0c;还以其深厚的品牌影响力、广泛的覆盖范围和高效的物流运作&#…

雅虎、乐天、煤炉、国际站、newegg、wish等跨境卖家如何提升店铺销量?深度解析自养号测评的价值

一、如何提升销量&#xff1f; 优化产品描述和图片&#xff1a;确保您的产品描述准确、详细&#xff0c;图片清晰、美观。这将有助于提高产品的吸引力&#xff0c;增加潜在买家的购买意愿。 提供良好的客户服务&#xff1a;及时回复买家的咨询和问题&#xff0c;解决他们的疑…

【MySQL】索引篇

SueWakeup 个人主页&#xff1a;SueWakeup 系列专栏&#xff1a;学习技术栈 个性签名&#xff1a;保留赤子之心也许是种幸运吧 本文封面由 凯楠&#x1f4f8;友情提供 目录 本系列传送门 1. 什么是索引 2. 索引的特性 3. 索引的分类 4. 索引的优点及缺点 优点 缺点 5.…

我的电脑图标没了怎么办?恢复图标只需一分钟!

“我打开电脑后&#xff0c;突然发现我的电脑图标没了&#xff0c;这是为什么呢&#xff1f;有什么方法可以找回我的电脑图标吗&#xff1f;” 在日常使用电脑的过程中&#xff0c;电脑桌面的各个图标是保证我们能正常打开应用的前提。我的电脑图标没了怎么办&#xff1f;这可能…

zabbix升级后图形文字不显示

原版本升级后版本6.4.76.4.13 问题现象 更新小版本后zabbix数据图形都有&#xff0c;只有下方文字不显示 处理方式 下载win字体&#xff0c;根据自己选择&#xff0c;上传至/usr/share/zabbix/assets/fonts目录下&#xff0c;修改文件名为jianti.ttf 修改默认字体配置文件…

CSS导读 (元素显示模式 上)

&#xff08;大家好&#xff0c;今天我们将继续来学习CSS的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 三、CSS的元素显示模式 3.1 什么是元素显示模式 3.2 块元素 3.3 行内元素 3.4 行内块元素 3.5 元素…

HashMap扩容原理(带源码分析)

HashMap的扩容原理 1.扩容流程图 注&#xff1a;拆分链表的规则 这里拆分链表时的一个比较&#xff1a;e.hash & oldCap 0 意思是&#xff1a;某一个节点的hash值和老数组容量求&运算。如果等于0&#xff0c;当前元素在老数组中的位置就是在新数组中的位置。如果不等…

CORS 跨域问题解决预检(OPTIONS)请求解释

场景&#xff1a; 业务要求从把系统B嵌入到系统A中&#xff0c;系统A和系统B是完成不同的两个域名&#xff0c;前端同事完成系统嵌入后&#xff0c;从A系统内部调用B系统的接口时候发现跨域错误&#xff08;CORS error&#xff09;&#xff0c;如下&#xff1a; 什么是跨域&…

vscode开发 vue3+ts 的 uni-app 微信小程序项目

创建uni-app项目&#xff1a; # 创建用ts开发的uni-app npx degit dcloudio/uni-preset-vue#vite-ts 项目名称 # 创建用js开发的uni-app npx degit dcloudio/uni-preset-vue#vite 项目名称VS Code 配置 为什么选择 VS Code &#xff1f; HbuilderX 对 TS 类型支持暂不完善VS…

(学习日记)2024.04.16:UCOSIII第四十四节:内存管理

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

手机数据恢复工具

下载地址&#xff1a;手机数据恢复工具.zip Android/HarmonyOS 文件误删是日常使用电子设备时经常遇到的问题&#xff0c;也许一不小心就就可能会误删。 俗话说&#xff1a;数据无价&#xff0c;一但想要找回一些被删除的文件&#xff0c;就需要耗费大量的精力和财力来恢复文…

【宝德PI300T G2智能小站开发教程(三)】centos配置系统开发源

目录 一.前言 二.配置dns服务器 三.测试连通性 四.设置更新源文件 一.前言 openeular系统的宝德板子没有更新的国内源,要如何配置? 二.配置dns服务器 vi /etc/resolv.conf 添加如下内容: nameserver 8.8.8.8 nameserver 114.114.114.114 三.测试连通性 ping www.ba…