VirtualApk源码分析-插件的加载

简介: 在进行插件化时,需要先将插件加载到当前进程中来,插件通常以APK的形式保存在SD卡上,VirtualApk加载插件的过程如下:PluginManager.loadPlugin---->LoadedPlugin.create,最终会创建LoadedPlugin对象,该对象就表示插件在内存中的存在形式。

在进行插件化时,需要先将插件加载到当前进程中来,插件通常以APK的形式保存在SD卡上,VirtualApk加载插件的过程如下:PluginManager.loadPlugin---->LoadedPlugin.create,最终会创建LoadedPlugin对象,该对象就表示插件在内存中的存在形式。

LoadedPlugin内部保存了如下变量:

img_35aed052b54fc9f6465ede25a06754f1.png
LoadedPlugin的内部变量

在创建LoadedPlugin的时候主要有如下操作,由于版面,这里分为Part1、Part2、Part3三个部分进行讲解。

Part1

img_296e5411ea284664e2ba9c5d7eb53f8a.png
Part1

PackageParser

在加载插件的时候,首先通过PackageParserCompat对插件APK进行解析,解析的时候巧妙得利用的Class加载中的双亲加载机制,先在PackageParserCompat中获取手机版本,然后再调用系统的PackageParser。

img_1befe62136e6606c92c1bf1312bf5b09.png
PackageParserCompat.parsePackage

接着根据版本调用不同的函数,例如:

img_c0fb2f6f8a5c61519bd3be9782b1d7f9.png
解析APK

这里巧妙了利用的Class的双亲加载机制,PackageParser是android.content.pm包下面的类,App是访问不到的。VirtualApk利用双亲加载机制的特点,在自己的包下面新建了一个相同包名和类名的Class,并实现了相同的API,这样在加载PackageParser时,双亲机制会优先加载Framework的PackageParser,这样就将解析APK的操作交给系统了。

img_0b47586c4bd599ccc8f0a1033d59424f.png
本地PackageParser

可以看到本地的PackageParser只是抛出异常,实际会调用Framework的parsePackage函数,完成APK解析。解析完成后就能获得APK的信息。接着创建插件的PluginContext、Resources、ClassLoader、Assets。

创建Resource

通过createResources函数可以创建插件的Resource。

img_bef51bd3eff5116aa5454da982d33591.png
createResources

这里传入的Context参数是宿主Context,VirtualApk提供了两种加载Resource的方式:

1、将插件宿主的Resource和插件Resource合并,宿主和插件使用同一个Resource,这样插件也能访问宿主的资源,宿主也能访问插件的资源。

img_445b59b0cd44e6b5dbaad9adc04377a4.png
ResourceManager.createResources

ResourceManager.createResources或许获取宿主Resources对象,然后反射创建AssetManager,然后在反射调用AssetManager.addAssetPath将宿主资源和插件的资源加进去(addAssetPath是hide函数,需要反射调用),最后再跟进不同的机型创建不同的Resources对象。ResourceManager.createResources之后调用了ResourcesManager.hookResources将宿主的Resource替换成合并后的Resources(反射替换ContexlImpl中mResources对象)。

img_44933736434164a585a89afa440bd7ba.png
hook掉宿主的Resource对象

2、为插件生成单独的Resources,宿主不能访问插件资源,但插件可以访问宿主资源。

img_59b5f7405c8cacfa604ba19814abbf25.png
反射创建Assetmanager

首先反射创建AssetManager并加入插件的资源,随后跟进AssetManager创建插件的Resources对象。

创建ClassLoader

ClassLoader主要是完成Class的加载,要加载插件APK内部的Class文件,就需要创建插件的ClassLoder对象。

img_6e51b601f057f2b11beb9bcd4860bcde.png
创建插件ClassLoader

Android为加载dex文件提供了两个类加载器:PathClassLoader和DexClassLoader,其中PathClassLoder用于加载安装好的APK,DexClassLoader可以加载SD卡下的APK文件。这两个ClassLoader都继承自BaseDexClassLoader。

img_c95de7a323ba8d8e069d13cf00e09e01.png
BaseDexClassLoader.findClass

BaseDexClassLoader.findClass将 加载Class的任务交给DexPathList

img_ab91939ba26878fc899b4a146e87bb8a.png
DexPathList,findClass

dexElements中存放了当前APK的多个dex文件,在加载Class的时候会按照dex的先后顺序完成Class的查找(插个题外话,QZone的热修复就是根据这个查找规则,将修复的Class放入一个全新的dex,然后将这个dex方法dexElements的第一个,这样就完成了修复)。

创建完插件的ClassLoder后,通过DexUtil.insertDex将插件的dex加入到宿主中去。

img_748151b580fe5d5168611cd24d0c536c.png
插件dex和宿主dex合并

拷贝SO

tryToCopyNativeLib实现SO的拷贝,将CPU-ABI对应的SO拷贝到宿主的context.getDir(Constants.NATIVE_DIR, Context.MODE_PRIVATE)目录下。

Part2

img_9775148cdbeba5bcc220b7eaad52eeeb.png
Part2

接下来将PackageParser解析到的InstrumentationInfo、ActivityInfo、ServiceInfo、ProviderInfo保存到本地的Map中。

Part3

img_aefa3787d9ff0f12a74bd71241bf3e4d.png
Part3

如果用户在插件中注册了静态广播,在加载插件的时候会把静态广播动态注册给mHostContext,,相当于把静态的插件广播动态注册到宿主中了,这样就完成了广播的插件化。

至此,整个插件的加载已经完成,生成了LoadedPlugin对象,并保存到PluginManager中。

目录
相关文章
|
9月前
|
存储 前端开发 Java
二十三.SpringCloudConfig源码-初始化配置
今天这篇文章我们来分析一下Spring Cloud Config 配置中心的源码,这应该是Spring Cloud Netflix的源码分析的最后一篇。下一个系列我将会继续分析Spring Cloud Alibaba相关组件的源码。Spring Cloud Config 基础使用请移步 《[配置中心Spring Cloud Config](https://blog.csdn.net/u014494148/article/details/117253831)》
|
10月前
|
存储 IDE Java
c++插件化 NDD源码的插件机制实现解析
c++插件化 NDD源码的插件机制实现解析
|
11月前
|
XML Java 程序员
【框架源码】SpringBoot核心源码解读之自动配置源码分析
【框架源码】SpringBoot核心源码解读之自动配置源码分析
【框架源码】SpringBoot核心源码解读之自动配置源码分析
|
11月前
|
Java Spring 容器
【框架源码】SpringBoot核心源码解读之启动类源码分析
【框架源码】SpringBoot核心源码解读之启动类源码分析
【框架源码】SpringBoot核心源码解读之启动类源码分析
|
编解码 安全 Java
Java通过jar包方式加载指定对象类教程以及源码分析
Java通过jar包方式加载指定对象类教程以及源码分析
394 0
Java通过jar包方式加载指定对象类教程以及源码分析
|
设计模式 前端开发 Java
六种方式实现 springboot 项目 启动预加载
六种方式实现 springboot 项目 启动预加载
1484 1
六种方式实现 springboot 项目 启动预加载
|
PHP
ThinkPHP自动加载Loader源码分析(4)
ThinkPHP自动加载Loader源码分析
95 0
ThinkPHP自动加载Loader源码分析(4)
|
PHP
ThinkPHP自动加载Loader源码分析(3)
ThinkPHP自动加载Loader源码分析
195 0
ThinkPHP自动加载Loader源码分析(3)
|
PHP
ThinkPHP自动加载Loader源码分析(1)
ThinkPHP自动加载Loader源码分析
127 0
ThinkPHP自动加载Loader源码分析(1)
|
PHP
ThinkPHP自动加载Loader源码分析(2)
ThinkPHP自动加载Loader源码分析
133 0
ThinkPHP自动加载Loader源码分析(2)

热门文章

最新文章