一.简介
java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。
ClassLoader的作用是:装载.class文件。Android 的 Dalvik/ART 虚拟机如同标准 Java 的 JVM 虚拟机一样,也是同样需要加载 class 文件到内存中来使用。使用的就是ClassLoader。
public abstract class ClassLoader {
}
classloader是个抽象类,Android中有一个BaseDexClassLoader类继承了ClassLoader。
public class BaseDexClassLoader extends ClassLoader {
}
而Android中常用的两个类DexClassLoader类和PathClassLoader类都继承了BaseDexClassLoader类。下面讲解DexClassLoader类和PathClassLoader类。因为这两个类最常用。
二.DexClassLoader类详解
1.源码
public class DexClassLoader extends BaseDexClassLoader {
public DexClassLoader(String dexPath, String optimizedDirectory,
String libraryPath, ClassLoader parent) {
super(dexPath, new File(optimizedDirectory), libraryPath, parent);
}
}
Android 8.0以后
public class DexClassLoader extends BaseDexClassLoader {
public DexClassLoader(String dexPath, String optimizedDirectory,
String librarySearchPath, ClassLoader parent) {
super(dexPath, null, librarySearchPath, parent);
}
}
2.参数
dexPath:dex文件路径列表,多个路径使用”:”分隔 。
optimizedDirectory:经过优化的dex文件(odex)文件输出目录 。
libPath:动态库路径(将被添加到app动态库搜索路径列表中)
parent:这是一个ClassLoader,这个参数的主要作用是保留java中ClassLoader的委托机制(优先父类加载器加载classes,由上而下的加载机制,防止重复加载类字节码)。
3.分析
源码分析可知:DexClassLoader比较简单。和PathClassLoader唯一区别就是多了optimizedDirectory参数。但从8.0开始optimizedDirectory已经弃用。从理论上来说,PathClassLoader应该可以完全替代DexClassLoader。
DexClassLoader是一个可以从包含classes.dex实体的.jar或.apk文件中加载classes的类加载器。可以用于实现dex的动态加载、代码热更新等等。这个类加载器必须要一个app的私有、可写目录来缓存经过优化的classes(odex文件),使用Context.getDir(String, int)方法可以创建一个这样的目录。
File dexOutputDir = context.getDir(“dex”, 0);
optimizedDirectory是用来缓存我们需要加载的dex文件的,并创建一个DexFile对象,如果它为null,那么会直接使用dex文件原有的路径来创建DexFile
对象。
optimizedDirectory必须是一个内部存储路径,无论哪种动态加载,加载的可执行文件一定要存放在内部存储。DexClassLoader可以指定自己的optimizedDirectory,所以它可以加载外部的dex,因为这个dex会被复制到内部路径的optimizedDirectory;而PathClassLoader没有optimizedDirectory,所以它只能加载内部的dex,这些大都是存在系统中已经安装过的apk里面的。
三.PathClassLoader类详解
1.源码
public class PathClassLoader extends BaseDexClassLoader {
public PathClassLoader(String dexPath, ClassLoader parent) {
super(dexPath, null, null, parent);
}
public PathClassLoader(String dexPath, String libraryPath,
ClassLoader parent) {
super(dexPath, null, libraryPath, parent);
}
}
2.参数
dexPath:文件或者目录的列表 。
libraryPath:包含lib库的目录列表 。
parent:ClassLoader 父类加载器。
3.分析
源码分析可知:PathClassLoader比较简单, 继承于BaseDexClassLoader. 默认 optimizedDirectory=null。
四.总结
DexClassLoader:能够加载未安装的jar/apk/dex。
PathClassLoader:只能加载系统中已经安装过的apk。
但是Android 8.0以上因为optimizedDirectory已经弃用。所以PathClassLoader也可以加载未安装的apk。也就是说Android8.0以上两个类是相同的。