每年这个时候,心里总是有两个事情挂念着。一个是准备过年回家,行李打包,机票买好,数着指头过日子就等那一天了。另一个事就没那么期待了,按照惯例,年前总要发一个新版本,抓住用户放假前最后一次露脸的机会,才算圆满。但是过年这几天,公司封网,渠道关闭,发出去的版本就像射出去的箭,你知道它出了问题,却只能眼睁睁看着,风险极大。如何控制风险,这真的是一门学问,但是即使有测试同学一个一个提BUG,灰度环境一次一次放量,还是难免有个别路径覆盖不到。用户反馈论坛炸了锅,面对这种情况,只有一个字,愁死人了。
愁也没用,我们来想想办法吧。最好的办法是让用户不知不觉的情况下更新版本。如果你的产品是一个网站,很简单,让程序员准备一个新版本然后按下发射按钮就行了。如果你的产品是移动端APP,无论是iOS还是Android,都绕不开用户授权安装这一步。什么,你说Android不是有静默安装这一招吗?好吧,这东西是需要Root权限的,Root权限是你想拿,想拿就能拿的吗?当然你要实在是想拿也不是不可以,改天我写篇文章讲一讲,你开心就好了。
此路不通,我们今天的主角要登场了。热补丁,可以做到线上推送一段修补BUG的代码,终端无需更新版本,直接运行。实现方式上,Android和iOS有所不同,限于篇幅今天讲讲Android的,iOS的后面补上。
这要从Android如何运行代码讲起。我们写Android程序,一般用JAVA语言。JAVA是一种高级语言,需要有个翻译器,把它翻译成CPU才懂的机器语言,这个翻译器就是虚拟机。打个比方,清朝的皇帝不懂汉语(别当真),要看懂汉臣们写的奏折,就要雇一个翻译官。翻译官的工作就是,一条条的读取奏折里的内容,翻译成满语,然后一条条呈递给皇帝。这个例子里,奏折是我们写的JAVA代码,翻译官是虚拟机,皇帝就是掌管一切的CPU。一般一段代码执行一个功能,比如从网上下载一首歌曲,就好比皇帝看到奏折之后,开始调度资源着手执行。
要实现热补丁,现在有两种主流的方法。一种是利用ClassLoader的方法,来自QQ空间团队。原理是虚拟机在翻译JAVA代码的时候,会把所有代码分成一个一个的dex(代码集合),依次执行。既然是依次执行,就有个谁先谁后的关系,我们只要把修复的代码段下载下来,改成跟原来有BUG的代码段一样的名字,插入到这个执行队列的最前面,那么运行的时候就会执行替身,真身永远都没有机会执行到。
讲人话就是,最开始的奏折都装在一个大箱子里的,翻译官会从这个大箱子里去取奏折来翻译。后来和珅灵机一动,把所有奏折分拆成很多份,装成一个一个的小箱子。为什么这样做呢?原来和珅虽然在朝中广结党羽,但是难免有几个「不识抬举」的,他们会时不时写一些「BUG奏折」揭发和珅。一开始的时候,举报奏折混在大箱子里,和珅即使知道也没办法阻止。现在好了,和珅知道哪个奏折是「BUG奏折」之后,就会伪造一个同名的「补丁奏折」,然后单独把它装在一个箱子里,把这个箱子放到所有箱子的最前面。翻译官第二天一大早起来翻译奏折的时候,拆开最前面的箱子,就会看到里面的奏折全是赞美和珅之辞,此时真正的「BUG奏折」正安静的躺在后面的某个箱子里,永远也不会被看到(因为虚拟机有个特性,同名的代码段不能有两个在同时运行)。
另一种方法叫Dexposed,来自阿里。这种方法更简单粗暴,它直接接管虚拟机的执行代码流程,本来虚拟机要执行一段有BUG代码,我们可以让它转而掉头去执行另一段没有BUG的代码。这下不得了了,推而广之,如果我们能诱导虚拟机执行任何我们想要的代码的话,你想想,这不是就是外挂吗?好在用这种方法你只能改你自己的APP,要想改别人的APP就要Root权限。还有,这种方法对5.0以上的Android系统不好使,原因是谷歌从5.0开始把虚拟机从Dalvik换成了ART。
还是看例子,和珅这次直接买通了翻译官,要求他每次看到举报和珅的「BUG奏折」之后,直接扔掉,用另一份准备好的「补丁奏折」替换之。然而,也不是人人都是可以被收买的,比如「Dalvik同志」就是自己人,「ART同志」就是一个两袖清风的人。
热补丁技术不光可以用来打补丁,还可以在线更新代码添加新需求。很神奇是吧?俗话说,只有想不到的需求,没有做不到的技术。如果你的产品还没用上这项技术,赶紧给他们提需求吧。
登录 | 立即注册