【Rust NDK】热修复?我用Rust实现一下

引言

前面几篇文章各位应该对 jni-rs 的了解比较清晰了。实际上在开发中,除去Rust所有权生命周期的折磨,大致的用法与C/C++写起来基本一致,而Rust的优势在我看来就是它的各类依赖都统一的放在 crates.io ,简单来说就是比较好找吧。

开发环境

操作系统:Windows 11

编码软件:Visual Studio Code 1.93.1 | Android Studio Ladybug | 2024.2.1 Beta 1

正文

本文将通过 jni-rs 与 Java 的深度结合,来在Rust层实现一个简单的Android热修复案例。

思路整理

首先呢,对于Android的热修复,通常都是通过 DexClassloader 去加载远程下放的 dex 文件,那当然了 InMemoryDexClassLoader 也是 api 28 之后常用的方式了。

本文就基于 DexClassloader的思路来实现一个简单的热修复so库。

熟悉热修复的各位都知道,当我们拿到热修复的 dex文件后,会将它的路径放到 DexPathListElement[] 数组的首位。

然后根据 Classloader 双亲委托的加载机制,当某个类被加载后,就会直接返回该类。而不会继续向后查找,这也就是为何要将热修复 dex 放在 Element[] 数组首位的原因。

创建Rust项目

还是老样子,我们创建名为 example_4 的Rust lib项目,然后通过 vscode 打开它。

image.png

接着,按照前几篇文章的步骤,改造这个项目。

image.png

开始创建初始化方法。

image.png

如上图,我们创建了一个 Java_com_hotfix_HotFix_init 的导出方法,它接收了两个参数 contextdex_path 分别对应 Android 中的 Context 上下文和自定义的热修复文件路径。

然后,通过第9行的红框代码,我们创建了一个mod名为 dex_installer 顾名思义就是对dex进行安装。

接着,第20行代码,我们拿到dex_path变量的Rust String类型的表示,并再次通过对dex_path的定义进行了变量遮掩。

最终,我们调用了dex_installer::install_dex自定的mod和自定义 install_dex 函数对dex进行热修复的安装。

实现install_dex函数

我们切换到定义好的dex_installmod下,进行函数逻辑的实现。

image.png

先写一段最基本的逻辑。

image.png

到这之后,我们创建好了新的 DexClassloadr 并且将 dex_path 的路径放了进去。

接下来就需要我们拿到 新创建的dex_class_loader原先Context的class_loaderDexPathList

因为两个 classloader 都需要拿到 DexPathList 这里就写一个函数 get_path_list

image.png

然后就是拿到 DexPathListElement[] 数组,再次封装成一个函数 get_dex_elements

image.png

我们再抽一下共用逻辑,得到最终的实现。

image.png

然后,补齐我们前面的 //to do,分别调用 get_path_listget_dex_elements 拿到两个 classloaderDexPathListelement[] 数组,如下图。

image.png

接下来呢,就需要对两个数组进行合并,并且对原来的 DexPathList 设置为合并后的 element[] 新值。

因此,我们还需要一个函数 combine_element_array 来对两个 element[] 数组进行合并。

image.png

最后,就可以补齐剩下的//to do了。

image.png

完整的 install_dex 函数实现,截图如下。

image.png

至此,一个简单的热修复实现就完成了。

编译为so库

最后,执行命令行代码,进行so的编译,得到 jniLibs 文件夹。

cargo ndk -t armeabi-v7a -t arm64-v8a -o ./jniLibs build --release

创建Android项目

接下来,我们创建一个Android项目并导入jniLibs测试一下。

创建hot子module

我们首先创建一个hot子module。

image.png

通过 Build->Rebuild Project 进行项目构建得到aar。

image.png

然后,通过压缩工具将这个arr文件中的 classes.jar 解压出来,我这里直接放到桌面上了。

image.png

最后通过 d8 命令行工具,将这个 jar 转为 dex 留作备用。

d8 --output=output_dex.jar input.jar

image.png

这时候再通过压缩工具打开classes_dex.jar就能得到dex文件了。

image.png

做完这一切后,我们的热修复dex总算是创建好了。

接下来,开始使用它。

image.png

创建好 jni 接口类和方法后,我们需要为 App 创建一个自定义的 Application,并复写它的 attachBaseContext 方法。

我们在app的外部私有目录下创建一个hotfix子目录,内部放入hotfix.dex(也就是刚才d8出来的dex文件,将它改名为hotfix.dex即可)。

这个就是需要被热修复的dex文件了。

image.png

image.png

接下来,最重要的一步来了。

只读引入hot子module

打开app的build.gradle.kts,将刚才创建的 hot module 进行只读引入。

image.png

然后在 MainActivity 中使用它。

image.png

最后,Run一下。

热修复

结果自然就可想而知了,肯定是崩溃的下场,因为这个类无法被找到。

image.png

那么我们将刚才的dex改名为 hotfix.dex 后推入设备上的指定目录中,让它能够被热修复加载。

image.png

之后,再次打开app。

image.png

就能够看见修复后的调用结果了。

文章至此,相信各位将这个例子敲下之后(加粗),就已经能够尝试在自己的项目中通过Rust来编写NDK的实现了。

那么,本篇完。

阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/22288,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?