一步步手动实现热修复(一)-dex文件的生成与加载

*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布

热修复技术自从QQ空间团队搞出来之后便渐渐趋于成熟。

我们这个系列主要介绍如何一步步手动实现基本的热修复功能,无需使用第三方框架。

在开始学习之前,需要对基本的热修复技术有些了解,以下文章可以帮助到你:

  • 安卓App热补丁动态修复技术介绍
  • 【腾讯Bugly干货分享】Android Patch 方案与持续交付
  • Android dex分包方案
  • dodola/HotFix

本节课程主要分为3块:

  • 1.一步步手动实现热修复(一)-dex文件的生成与加载
  • 2.一步步手动实现热修复(二)-类的加载机制简要介绍
  • 3.一步步手动实现热修复(三)-Class文件的替换

本节示例所用到的任何资源都已开源,项目中包含工程中所用到代码、示例图片、说明文档。项目地址为:
https://code.csdn.net/u011064099/sahadevhotfix/tree/master

dex文件的生成与加载

我们在这部分主要做的流程有:

  • 1.编写基本的Java文件并编译为.class文件。
  • 2.将.class文件转为.dex文件。
  • 3.将转好的dex文件放入创建好的Android工程内并在启动时将其写入本地。
  • 4.加载解压后的.dex文件中的类,并调用其方法进行测试。

Note: 在阅读本节之前最好先了解一下类加载器的双亲委派原则、DexClassLoader的使用以及反射的知识点。

编写基本的Java文件并编译为.class文件

首先我们在一个工程目录下开始创建并编写我们的Java文件,你可能会选择各种IDE来做这件事,但我在这里劝你不要这么做,因为有坑在等你。等把基本流程搞清楚可以再选择更进阶的方法。这里我们可以选择文本编辑器比如EditPlus来对Java文件进行编辑。

新建一个Java文件,并命名为:ClassStudent.java,并在java文件内键入以下代码:

public class ClassStudent {private String name;public ClassStudent() {}public void setName(String name) {this.name = name;}public String getName(){return this.name + ".Mr";   }
}

Note: 这里要注意,不要对类添加包名,因为在后期对class文件处理时会遇到问题,具体问题会稍后说明。上面的getName方法在返回时对this.name属性添加了一段字符串,这里请注意,后面会用到。

在文件创建好之后,对Java文件进行编译:
这里写图片描述

将.class文件转为.dex文件

好,现在我们使用class文件生成对应的dex文件。生成dex文件所需要的工具为dx,dx工具位于sdk的build-tools文件夹内,如下图所示:
这里写图片描述

Tips: 为了方便使用,建议将dx的路径添加到环境变量中。如果对dx工具不熟悉的,可以在终端中输入dx –help以获取帮助。

dx工具的基本用法是:

dx --dex [--output=<file>] [<file>.class | <file>.{zip,jar,apk} | <directory>]

Tips: 刚开始自己摸索的时候,就没有仔细看命令,导致后面两个参数的顺序颠倒了,搞出了一些让人疑惑难解的问题,最后又不得不去找dx工具的源码调试,最后才发现自己的问题在哪。如果有对dx工具感兴趣的,可以对dx的包进行反编译或者获取dx的相关源代码进行了解。dx.lib文件位于dx.bat的下级目录lib文件夹中,可以使用JD-GUI工具对其进行查看或导出。如果需要获取源代码的,请使用以下命令进行克隆:

git clone https://android.googlesource.com/platform/dalvik

我们使用以下命令生成dex文件:

dx --dex --output=user.dex ClassStudent.class

这里我为了防止出错,提前在当前目录下新建好了user.dex文件。上述命令依赖编译.class文件的JDK版本,如果使用的是JDK8编译的class会提示以下问题:

PARSE ERROR:
unsupported class file version 52.0
...while parsing ClassStudent.class
1 error; aborting

这里的52.0意味着class文件不被支持,需要使用JDK8以下的版本进行编译,但是dx所需的环境还是需要为JDK8的,这里我编译class文件使用的是JDK7,请注意。

上面我们提到了为什么先不要在ClassStudent中使用包名,因为在执行dx的时候会报以下异常,这是因为以下第二项条件没有通过,该代码位于com.android.dx.cf.direct.DirectClassFile文件内:

    String thisClassName = thisClass.getClassType().getClassName();if(!(filePath.endsWith(".class") && filePath.startsWith(thisClassName) && (filePath.length()==(thisClassName.length()+6)))){throw new ParseException("class name (" + thisClassName + ") does not match path (" + filePath + ")");}

运行截图如下所示:
这里写图片描述

好了,到此为止我们的目录应该如下:
这里写图片描述

写入dex到本地磁盘

接下来将生成好的user.dex文件放入Android工程的res\raw文件夹下:
这里写图片描述

在系统启动时将其写入到磁盘,这里不再贴出具体的写入代码,项目的MainActivity中包含了此部分代码。

加载dex中的类并测试

在写入完毕之后使用DexClassLoader对其进行加载。DexClassLoader的构造方法需要4个参数,这里对这4个参数进行简要说明:

  • String dexPath:dex文件的绝对路径。在这里我将其放入了应用的cache文件夹下。
  • String optimizedDirectory:优化后的dex文件存放路径。DexClassLoader在构造完毕之后会对原有的dex文件优化并生成一个新的dex文件,在这里我选择的是…/cache/optimizedDirectory/目录。此外,API文档对该目录有严格的说明:Do not cache optimized classes on external storage.出于安全考虑,请不要将优化后的dex文件放入外部存储器中。
  • String libraryPath:dex文件所需要的库文件路径。这里没有依赖,使用空字符串代替。
  • ClassLoader parent:双亲委派原则中提到的父类加载器。这里我们使用默认的加载器,通过getClassLoader()方法获得。

在解释完毕DexClassLoader的构造参数之后,我们开始对刚刚的dex文件进行加载:

DexClassLoader dexClassLoader = new DexClassLoader(apkPath, file.getParent() + "/optimizedDirectory/", "", classLoader);

接来下开始load我们刚刚写入在dex文件中的ClassStudent类:

Class<?> aClass = dexClassLoader.loadClass("ClassStudent");

然后我们对其进行初始化,并调用相关的get/set方法对其进行验证,在这里我传给ClassStudent对象一个字符串,然后调用它的get方法获取在方法内合并后的字符串:

    Object instance = aClass.newInstance();Method method = aClass.getMethod("setName", String.class);method.invoke(instance, "Sahadev");Method getNameMethod = aClass.getMethod("getName");Object invoke = getNameMethod.invoke(instance););

最后我们实现的代码可能是这样的:

    /*** 加载指定路径的dex** @param apkPath*/private void loadClass(String apkPath) {ClassLoader classLoader = getClassLoader();File file = new File(apkPath);try {DexClassLoader dexClassLoader = new DexClassLoader(apkPath, file.getParent() + "/optimizedDirectory/", "", classLoader);Class<?> aClass = dexClassLoader.loadClass("ClassStudent");mLog.i(TAG, "ClassStudent = " + aClass);Object instance = aClass.newInstance();Method method = aClass.getMethod("setName", String.class);method.invoke(instance, "Sahadev");Method getNameMethod = aClass.getMethod("getName");Object invoke = getNameMethod.invoke(instance);mLog.i(TAG, "invoke result = " + invoke);} catch (Exception e) {e.printStackTrace();}}

最后附上我们的运行截图:
这里写图片描述

如果在实现过程中遇到问题的,请在下方留言。

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

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

相关文章

美团酒旅实时数据规则引擎应用实践

背景 美团点评酒旅运营需求在离线场景下&#xff0c;已经得到了较为系统化的支持&#xff0c;通过对离线数据收集、挖掘&#xff0c;可对目标用户进行T1触达&#xff0c;通过向目标用户发送Push等多种方式&#xff0c;在一定程度上提高转化率。但T1本身的延迟性会导致用户在产生…

开直播辣!生成对抗网络全脉络梳理!

深度学习中最有趣的方法是什么&#xff1f;GAN&#xff01;最近最火的AI技术是什么&#xff1f;GAN&#xff01;&#xff01;你现在脑子里在想什么&#xff1f;搞定GAN&#xff01;&#xff01;&#xff01;【已经大彻大悟要直接报名公开课、挑战万元奖品池的请划到最后】GAN真…

论文浅尝 - ICLR2020 | 具有通用视觉表示的神经机器翻译

论文笔记整理&#xff1a;柏超宇&#xff0c;东南大学在读硕士。来源&#xff1a;ICLR2020 https://openreview.net/forum?idByl8hhNYPS代码链接&#xff1a;https://github.com/cooelf/UVR-NMT简介和动机近年来&#xff0c;不少工作已经证明了视觉信息在机器翻译&#xff08;…

知识图谱能否拯救NLP的未来?

文 | Luke知乎知识图谱是NLP的未来吗&#xff1f;2021年了&#xff0c;不少当年如日中天技术到今天早已无人问津&#xff0c;而知识图谱这个AI界的大IP最火的时候应该是18&#xff0c;19年&#xff0c;彼时上到头部大厂下到明星创业公司都在PR自己图谱NLP布局能够赋予AI认知能力…

论文浅尝 | Data Intelligence 已出版的知识图谱主题论文

本文转载自公众号&#xff1a;DI数据智能。 知识图谱被称为人工智能的基石&#xff0c;它的前身是语义网&#xff0c;由谷歌在2012年率先提出&#xff0c;用于改善自身的搜索业务。Data Intelligence执行…

一步步手动实现热修复(三)-Class文件的替换

*本篇文章已授权微信公众号 guolin_blog &#xff08;郭霖&#xff09;独家发布 本节课程主要分为3块&#xff1a; 1.一步步手动实现热修复(一)-dex文件的生成与加载2.一步步手动实现热修复(二)-类的加载机制简要介绍3.一步步手动实现热修复(三)-Class文件的替换 本节示例所…

Vision Transformer 论文解读

原文链接&#xff1a;https://blog.csdn.net/qq_16236875/article/details/108964948 扩展阅读&#xff1a;吸取CNN优点&#xff01;LeViT&#xff1a;用于快速推理的视觉Transformer https://zhuanlan.zhihu.com/p/363647380 Abstract: Transformer 架构早已在自然语言处理…

长这么大,才知道数据集不用下载可以直接在线使用

每天清晨打开电脑&#xff0c;搜索所需的数据集&#xff0c;点击“Download”&#xff0c;愉快地眯上眼睛&#xff0c;期待n个小时后醒来乖巧下载好的数据&#xff0c;开始放进模型像小仓鼠进滚轮一样快乐奔跑。梦醒时分&#xff0c;一个“Error”蹦进眼睛里&#xff0c;美好码…

会议交流 - CCKS2020 | 2020年全国知识图谱与语义计算大会

OpenKG开放知识图谱&#xff08;简称 OpenKG&#xff09;旨在促进中文知识图谱数据的开放与互联&#xff0c;促进知识图谱和语义技术的普及和广泛应用。

LeetCode 739. 每日温度(单调栈)

1. 题目 根据每日 气温 列表&#xff0c;请重新生成一个列表&#xff0c;对应位置的输入是你需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高&#xff0c;请在该位置用 0 来代替。 例如&#xff0c;给定一个列表 temperatures [73, 74, 75, 71, 69, 72, 76, …

令人振奋的好消息!2016年12月8日Google Developers中文网站发布!

令人振奋的好消息&#xff01; 2016年12月8日Google Developers中文网站发布&#xff01; 以往我们需要访问Android的开发网站、Google的开发网站都需要翻墙&#xff0c;苦不堪言。现在Google发布了中文网站&#xff0c;怎能不让人开心&#xff1f;&#xff01; Android中文…

美团外卖Android Lint代码检查实践

概述 Lint是Google提供的Android静态代码检查工具&#xff0c;可以扫描并发现代码中潜在的问题&#xff0c;提醒开发人员及早修正&#xff0c;提高代码质量。除了Android原生提供的几百个Lint规则&#xff0c;还可以开发自定义Lint规则以满足实际需要。 为什么要使用Lint 在美团…

这篇论文提出了一个文本-知识图谱的格式转换器...

文 | 花小花PosyHello, 大家好&#xff0c;我是小花。今天给大家介绍一篇有野心的paper。为何如此说呢&#xff1f;因为该工作提出了一个知识的格式转换器&#xff0c;用于转换 无结构化的纯文本(Text)和结构化的知识图谱(KG) 。换句话说&#xff0c;给模型一打句子&#xff0c…

论文小综 | Using External Knowledge on VQA

本文转载自公众号&#xff1a;浙大KG。本文作者&#xff1a;陈卓&#xff0c;浙江大学在读博士&#xff0c;主要研究方向为图神经网络和知识图谱表示学习我们生活在一个多模态的世界中。视觉的捕捉与理解&#xff0c;知识的学习与感知&#xff0c;语言的交流与表达&#xff0c;…

如何修改TextView链接点击实现(包含链接生成与点击原理分析)

*这篇文章的主要目的是想要大家学习如何了解实现&#xff0c;修改实现&#xff0c;以达到举一反三&#xff0c;自行解决问题的目的。 某天遇到这么一个需求&#xff1a;在TextView中的文本链接要支持跳转&#xff0c;嗯&#xff0c;这个好办&#xff0c;TextView本身是支持的&…

LeetCode 752. 打开转盘锁(图的BFS最短路径)

1. 题目 你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字&#xff1a; ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由旋转&#xff1a;例如把 ‘9’ 变为 ‘0’&#xff0c;‘0’ 变为 ‘9’ 。每次旋转都只能旋转一个拨…

使用TensorFlow训练WDL模型性能问题定位与调优

简介 TensorFlow是Google研发的第二代人工智能学习系统&#xff0c;能够处理多种深度学习算法模型&#xff0c;以功能强大和高可扩展性而著称。TensorFlow完全开源&#xff0c;所以很多公司都在使用&#xff0c;但是美团点评在使用分布式TensorFlow训练WDL模型时&#xff0c;发…

会议交流 - CNCC 技术论坛 | NLP中知识和数据怎么选?当然是全都要!——第四届中文信息技术发展战略研讨会...

本文转载自公众号&#xff1a;中国计算机学会 。本论坛将于CNCC2020期间&#xff0c;10月23日下午16:00-18:00&#xff0c;在北京新世纪日航饭店3层南京厅举行。本论坛将邀请多位来自国内著名高校和人工智能企业的知名自然语言处理专家介绍他们在知识图谱、知识获取、预训练模型…

从我开发过的Tensorflow、飞桨、无量框架看深度学习这几年

文 | Peter潘欣知乎和深度学习框架打交道已有多年时间。从Google的TensorFlow, 到百度的PaddlePaddle&#xff0c;再到现在腾讯的无量。很庆幸在AI技术爆发的这些年横跨中美几家公司&#xff0c;站在一个比较好的视角看着世界发生巨大的变化。在这些经历中&#xff0c;视角在不…

探索Glide对Gif图片资源的获取、解析过程

先预祝大家汤圆节快乐&#xff01;很久没写博客了。今天我们来探索一下Glide是如何支持Gif图片加载的。 本篇博客的目的 了解代码分析的基本思路与方法了解Glide是如何对Gif图片进行支持的 探索背景 为什么会有这么一个想法呢&#xff0c;一来一直对Glide是知其名而不知其所…