ClassLoader
在Java中的类,都是需要先被ClassLoader加载,然后再使用。
在Android开发中,可以使用java、kotlin、flutter等语言编写程序,但是最后都是被编译为字节码文件,这些字节码文件都是给Android虚拟机识别,然后转换为机器码给操作系统执行,这样的一个过程被称为"解释",英文为:interpret。
虚拟机要识别一个类,首先要拿到这个类,如何拿到呢?读字节码文件,如何读?通过ClassLoader类。
ClassLoader是如何生成的呢?
与TLS连接的服务器证书原理中的根证书类似,会由虚拟机创建一个根ClassLoader以及由它加载出来的其它的ClassLoader,然后就可以加载出各个需要的字节码文件,每一个ClassLoader会在运行时去需要的目录寻找字节码文件。
所以解释的过程大致就是:
- Java虚拟机创建一个根ClassLoader以及这个ClassLoader加载出来的其它ClassLoader,然后在它们需要的目录寻找字节码文件转换为java class,最后虚拟机将其转换为机器码给到操作系统执行。
组件化
在Android中,组件化就是将项目分成多个Module进行开发,以达到复用、降低耦合等目的。
插件化
如果说组件化是静态的、编译时的先发,插件化是动态的、运行时后发。
在Android中,插件化就是将一些模块进行独立拆分,不包含进原始的APK包中,等到需要的时机再进行动态的加载,也就是将编译完成的字节码包进行动态加载,这些字节码包称之为插件。
加载字节码需要ClassLoader,在Android中存在DexClassLoader等可以在指定路径加载Dex文件,Dex文件是多个字节码文件组成的集合体,是Dalvik Executable文件,也就是Android虚拟机可执行文件。
插件化Sample
//拷贝assets目录中的插件到cache目录
File apk = new File(getCacheDir() + "/plugin-debug.apk");
try (Source source = Okio.source(getAssets().open("apk/plugin-debug.apk"));
BufferedSink sink = Okio.buffer(Okio.sink(apk))){
sink.writeAll(source);
} catch (Exception e) {
e.printStackTrace();
}
//使用DexClassLoader加载cache目录中的插件,反射调用插件中的功能
DexClassLoader classLoader = new DexClassLoader(apk.getPath(), getCacheDir().getPath(), null, null);
try {
Class pluginUtilsClass = classLoader.loadClass("com.example.plugin.Utils");
Constructor utilsConstructor = pluginUtilsClass.getDeclaredConstructors()[0];
Object utils = utilsConstructor.newInstance();
Method shoutMethod =<