您的位置:首页 > 移动开发 > Android开发

android类加载器的讨论

2015-11-23 11:31 232 查看
新建宿主工程Host,导出接口类PluginInterface,新建插件工程Plugin,导入该接口类,然后由宿主加载该插件。看能否成功调起。

接下来,做四个实验,再对实验结果进行分析。在实验之前,先说一下jar包的引用方式。eclipse下对jar包的引用分两种:内引用和外引用。内引用表示打包时会带上该jar包,外引用打包时不会带上该jar包。而libs目录下的jar包都默认为内引用,所以如果有外引用的jar包,需要另外建立一个目录如libs_ex,然后在eclipse中以add external jar的方式导入。

一、插件以内引用方式导入接口类,宿主也是内引用方式导入接口,插件的DexClassLoader的父ClassLoader设为宿主的ClassLoader,运行时会报以下错误:



错误的原因在于在加载插件中的接口类时会首先在其父加载器中查找,而宿主的加载器中已存在该类了,所以插件中的接口类就会由宿主的加载器加载,这就会导致宿主的加载器同时加载两个相同的类,这种情况是不允许出现的,因此抛出异常。如果两个相同的类分由两个独立的加载器加载,就不会有问题。比如插件A中要用到某开源库,插件B中也要用到该开源库,则可以将该开源库以内部引用的方式导入到宿主中,插件们都以外部引用的方式导入该库,或者宿主不引用该库,由插件各自以内部引用的方式导入该库。当然,如果该开源库被各插件使用的很频繁,较好的办法是由宿主导入,这样可以减少各插件包的体积。

二、宿主以外引用方式导入接口,插件以内引用方式导入接口,插件的DexClassLoader的父ClassLoader设为宿主的ClassLoader,运行时会报以下错误



错误的原因在于宿主以外部引用方式导入该接口,所以打包时没有导入该接口类,这样运行时就会找不到该接口。

三、插件以内引用方式导入接口,宿主以内引用方式导入接口,但将插件的DexClassLoader的父ClassLoader设为ClassLoader.getSystemClassLoader,运行时会报以下错误



崩溃的原因大意是类型转换时错误,而看这两个类名都完全一样,所以问题在于类加载器不同。定义类是否相同得同时看类名和类加载器是否完全相同。这里插件在加载接口类时首先到其父加载器中查找,而父加载器是SystemClassLoader,所以找不到该接口类,那么只能用DexClassLoader在插件中查找,由于接口类是内引用打包进了插件apk,所以找到了。而宿主中的接口类也是内引用方式,所以宿主的ClassLoader也找到了该接口类,虽然插件和宿主中的接口类完全一样,但是是由不同的类加载器加载的,所以在做类型转换时出错。

四、插件以外阴用方式导入接口,宿主以内引用方式导入接口,但将插件的DexClassLoader的父ClassLoader设为ClassLoader.getSystemClassLoader,运行时会报以下错误



插件在加载该接口类时,首先用父加载器即SystemClassLoader查找该类,由于找不到,所以在插件内找,由于是外部打包方式,所以也找不到。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: