【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 打开它。

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

开始创建初始化方法。

如上图,我们创建了一个 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下,进行函数逻辑的实现。

先写一段最基本的逻辑。

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

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

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

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

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

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

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

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

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

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

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

编译为so库

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

bash 复制代码
cargo ndk -t armeabi-v7a -t arm64-v8a -o ./jniLibs build --release

创建Android项目

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

创建hot子module

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

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

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

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

bash 复制代码
d8 --output=output_dex.jar input.jar

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

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

接下来,开始使用它。

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

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

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

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

只读引入hot子module

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

然后在 MainActivity 中使用它。

最后,Run一下。

热修复

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

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

之后,再次打开app。

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

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

那么,本篇完。

相关推荐
还鮟1 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡3 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi003 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil4 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android
你过来啊你4 小时前
Android View的绘制原理详解
android
移动开发者1号7 小时前
使用 Android App Bundle 极致压缩应用体积
android·kotlin
移动开发者1号7 小时前
构建高可用线上性能监控体系:从原理到实战
android·kotlin
ii_best12 小时前
按键精灵支持安卓14、15系统,兼容64位环境开发辅助工具
android
美狐美颜sdk12 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
恋猫de小郭17 小时前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin