博客
关于我
Android热修复升级探索——SO库修复方案
阅读量:148 次
发布时间:2019-02-27

本文共 1755 字,大约阅读时间需要 5 分钟。

Android热补丁方案:SO库修复的实现与分析

在Android开发中,热补丁方案旨在在不重新启动应用程序的情况下修复已安装的应用程序。通常情况下,开发者希望通过热补丁实现多方面的修复,包括类修复、资源修复以及SO库的修复。以下将详细介绍Android下的SO库修复思路,分析其实现原理以及在不同虚拟机(如Dalvik和Art)下的兼容性问题。


一、SO库加载原理

在Android中,Java API提供了两种加载SO库的接口:

  • System.loadLibrary(String libName):传入的参数是SO库的名称,表示SO库文件位于APK压缩文件中的libs目录下。系统会将该SO库复制到APK安装目录下,最后通过nativeLoad方法加载该SO库。

  • System.load(String pathName):传入的参数是SO库在磁盘中的完整路径,用于加载一个自定义外部的SO库文件。

  • 这两种方式最终都调用nativeLoad方法来加载SO库,参数为SO库的文件名。JNI编程中,动态注册的native方法必须实现JNI_OnLoad方法,而静态注册的native方法则必须以类名+方法名的格式进行注册。


    二、SO库热部署实时生效可行性分析

    为了实现SO库的实时修复,我们需要分析动态注册和静态注册native方法在不同虚拟机下的兼容性。

    1. 动态注册native方法实时生效

    动态注册的native方法通过JNI_OnLoad方法重新映射,前提是SO库已经加载过一次。我们可以先加载原SO库,然后再加载补丁SO库,从而实现动态注册native方法的实时修复。

    关键点:

    • Dalvik虚拟机:在Dalvik中,通过修改SO库的文件名(例如添加时间戳),确保在hashtable中查找到的句柄指向补丁SO库,从而实现动态注册方法的实时生效。
    • Art虚拟机:Art虚拟机直接通过System.load方法加载补丁SO库,调用补丁SO库的JNI_OnLoad方法,实现动态注册方法的实时生效。

    2. 静态注册native方法实时生效

    静态注册的native方法在第一次执行时完成映射,无法直接通过补丁SO库实现实时修复。我们需要解注册这些方法,然后重新加载补丁SO库。

    关键点:

    • 需要解注册静态注册的native方法,重新加载补丁SO库。
    • 由于无法直接知道哪些静态注册的native方法发生了变更,需依赖补丁SO库的重命名来确保加载新的方法。

    三、SO库实时生效的局限性

    尽管SO库的实时生效在动态注册方法中实现了兼容性,但静态注册方法的实时修复存在局限性:

    • 需要解注册静态注册的native方法,这在实际应用中难以实现,因为无法直接知道哪些方法发生了变更。
    • 补丁SO库的加载可能导致内存泄漏或OutOfMemoryError(OOM),尤其是在SO库较大或补丁较多的情况下。

    因此,最终放弃了SO库的实时生效需求,转而采用冷部署重启生效的方案。


    四、SO库冷部署重启生效的实现方案

    方案1:接口调用替换

    通过替换System.loadLibrary接口,优先加载补丁SO库:

    • 如果存在补丁SO库,优先加载补丁SO库;否则加载原SO库。

    优点:无需对不同SDK版本进行区分处理,实现简单。

    缺点:需要强制侵入用户接口调用,无法修复三方库的SO库。

    方案2:反射注入

    通过反射注入修改DexPathList.findLibrary方法,插入补丁SO库的路径:

    • 在findLibrary方法中,插入补丁SO库的路径到nativeLibraryDirectories数组的最前面。

    优点:可以修复三方库的SO库,不依赖于用户接口调用。

    缺点:需对SDK进行适配,findLibrary实现在SDK23之前和之后有所不同。同时,需选择合适的CPU架构的SO库文件进行修复。


    五、小结

    SO库修复方案目前主要采用接口调用替换和反射注入两种方式:

    • 接口调用替换:简单易行,但无法修复三方库的SO库。
    • 反射注入:实现普适性更强,但需对SDK进行适配。

    对于实时生效的需求,可以通过SO库的重命名确保动态注册方法的实时生效,但静态注册方法仍存在局限性。因此,推荐采用冷部署重启生效的方案,兼顾通用性和实现复杂度。

    转载地址:http://vkrb.baihongyu.com/

    你可能感兴趣的文章
    Python关于numpy.transpose函数详细解析附代码
    查看>>
    Python3导入自定义模块的3种方式
    查看>>
    python3打开txt文件_使用Python 3从文本文件读取句子并添加到列表中
    查看>>
    python3爬虫抓取智联招聘职位信息代码
    查看>>
    Python3爬虫数据入数据库---把爬取到的数据存到数据库,带数据库去重功能
    查看>>
    python3的 pymysql把mysqldb库取代了,让python 3支持mysqldb的解决方法
    查看>>
    Python3笔记——IDE的选择
    查看>>
    python3简单使用requests 用户代理,cookie池
    查看>>
    Python3组播通信编程实现教程(发送者+接收者)
    查看>>
    Python3编写网络爬虫10-数据存储方式三-CSV文件存储
    查看>>
    python3读取redis返回数据带有'b'的问题
    查看>>
    Python3连接MySQL
    查看>>
    Python关于isinstance函数的解析 | 附Demo(全)
    查看>>
    Python3:setup.py:完成所有任务的PIP安装(Build_ext+Install)
    查看>>
    python4.0 gil_Python 并发编程系列--1、浅谈GIL历史及对多线程的影响
    查看>>
    python60行绘图程序_天底下最简单的QT画图板,就一个类,60行代码
    查看>>
    Python: AES加密与解密
    查看>>
    Python: Range() 最大尺寸;动态的还是静态的?
    查看>>
    Python: Windows下用 multiprocessing 的深坑
    查看>>
    python:Could not find platform independent libraries <prefix>解决方法
    查看>>