• 面试:插件化相关---so


    关于so库的一些常识

    宿主与插件中so库加载区别 :

    • 宿主应用程序 :build 生成apk ,不需要开发者自己去判断ABI,Android系统在安装APK的时候,不会安装APK里面全部的so库文件,而是会根据当前CPU类型支持的ABI,从APK里面拷贝最合适的so库,并保存在APP的内部存储路径的libs 下面。

    • 插件应用程序apk : 动态加载插件的so,需要我们判断ABI类型来加载相应的so,Android系统不会帮我们处理。

    加载so的两种方式 :

    • System.load():参数必须为库文件的绝对路径(注意点:不能放在sdcard中)

    • System.loadLibrary(): 参数为库文件名,不包含库文件的扩展名

    接下来,根据framework层中的源码,来了解native是如何加载,如何查找的。

    PathClassLoader是如何加载代码过程

    应用程序会通过PathClassLoader加载java和c++的代码

    HookDemo/Android插件化之so加载.md at master · 13767004362/HookDemo · GitHub 

    只要将插件中的so库放到nativeLibraryPathElements中,就可以自然而然的加载插件中c++代码了。

    实战

    1. 将插件中so库解压到手机磁盘
    2. 获取到宿主中so库,与插件中so库合并收集。

    1、在插件项目中先编写c++代码文件,生成对应的cpu的so库,通过System.loadLibrary()加载so库

    2、接下来在宿主中编写。先根据手机cpu进行筛选,加载相应的so库,将宿主中so资源与插件so资源进行合并:

    1. // 获取到DexPathList对象
    2. Class<?> baseDexClassLoaderClass = DexClassLoader.class.getSuperclass();
    3. Field pathListField = baseDexClassLoaderClass.getDeclaredField("pathList");
    4. pathListField.setAccessible(true);
    5. Object dexPathList = pathListField.get(appClassLoader);
    6. /**
    7. * 接下来,合并宿主so,系统so,插件so库
    8. */
    9. Class<?> DexPathListClass = dexPathList.getClass();
    10. if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
    11. // 先创建一个汇总so库的文件夹,收集全部
    12. List<File> allNativeLibDirList = new ArrayList<>();
    13. // 先添加插件的so库地址
    14. allNativeLibDirList.addAll(pluginNativeLibraryDirList);
    15. // 获取到宿主的so库地址
    16. Field nativeLibraryDirectoriesField = DexPathListClass.getDeclaredField("nativeLibraryDirectories");
    17. nativeLibraryDirectoriesField.setAccessible(true);
    18. List<File> old_nativeLibraryDirectories = (List<File>) nativeLibraryDirectoriesField.get(dexPathList);
    19. allNativeLibDirList.addAll(old_nativeLibraryDirectories);
    20. // 获取到system的so库地址
    21. Field systemNativeLibraryDirectoriesField = DexPathListClass.getDeclaredField("systemNativeLibraryDirectories");
    22. systemNativeLibraryDirectoriesField.setAccessible(true);
    23. List<File> systemNativeLibraryDirectories = (List<File>) systemNativeLibraryDirectoriesField.get(dexPathList);
    24. allNativeLibDirList.addAll(systemNativeLibraryDirectories);
    25. //通过makePathElements获取到c++存放的Element
    26. Method makePathElementsMethod = DexPathListClass.getDeclaredMethod("makePathElements", List.class, List.class, ClassLoader.class);
    27. makePathElementsMethod.setAccessible(true);
    28. Object[] allNativeLibraryPathElements = (Object[]) makePathElementsMethod.invoke(null, allNativeLibDirList, new ArrayList<IOException>(), appClassLoader);
    29. //将合并宿主和插件的so库,重新设置进去
    30. Field nativeLibraryPathElementsField = DexPathListClass.getDeclaredField("nativeLibraryPathElements");
    31. nativeLibraryPathElementsField.setAccessible(true);
    32. nativeLibraryPathElementsField.set(dexPathList, allNativeLibraryPathElements);
    33. } else {
    34. // 获取到宿主的so库地址
    35. Field nativeLibraryDirectoriesField = DexPathListClass.getDeclaredField("nativeLibraryDirectories");
    36. nativeLibraryDirectoriesField.setAccessible(true);
    37. File[] oldNativeDirs = (File[]) nativeLibraryDirectoriesField.get(dexPathList);
    38. int oldNativeLibraryDirSize = oldNativeDirs.length;
    39. // 创建一个汇总宿主,插件的so库地址的数组
    40. File[] totalNativeLibraryDir = new File[oldNativeLibraryDirSize + pluginNativeLibraryDirList.size()];
    41. System.arraycopy(oldNativeDirs, 0, totalNativeLibraryDir, 0, oldNativeLibraryDirSize);
    42. for (int i = 0; i < totalNativeLibraryDir.length; ++i) {
    43. totalNativeLibraryDir[oldNativeLibraryDirSize + i] = pluginNativeLibraryDirList.get(i);
    44. }
    45. // 替换成合并的so库资源数组
    46. nativeLibraryDirectoriesField.set(dexPathList, totalNativeLibraryDir);
    47. }
  • 相关阅读:
    spark完全分布式部署
    Win10系统Charles/Fiddler抓包无反应处理
    Spring常见问题解决 - @PathVariable 解析带 / 的参数值报404
    3D印刷电路板在线渲染查看工具
    【torch高级】一种新型的概率学语言pyro(01/2)
    基于PHP+MySQL动漫社管理系统的设计与实现
    Rasa 3.x 学习系列-Rasa 3.2.1 新版本发布
    既然有了量化交易,技术分析还有存在的必要么?有专门收割自动交易系统的策略吗?
    GIS跟踪监管系统
    一天一八股——SSL/TLS协议
  • 原文地址:https://blog.csdn.net/cpcpcp123/article/details/128112195