android中,dalvik虚拟机加载的是dex文件,用于加载类的ClassLoader是PathClassLoader和DexClassLoader。PathClassLoader和DexClassLoader都继承自BaseDexClassLoader,它们的父ClassLoader为BootClassLoader。
回顾在JVM中,自定义的ClassLoader一般直接继承自ClassLoader类,为了满足双亲委派模型,重写findClass类来将类的全限定名转化为Class。在findClass中,一般会调用ClassLoader的defineClass方法来将byte[]形式的JVM字节码转化为对应的Class。
但是在dalvik虚拟机上,JVM的字节码是无法运行在上面执行的,所以不能通过defineClass来生成dalvik所需要的类。dalvik为了解决这个问题,在android上加载类的ClassLoader主要为PathClassLoader和DexClassLoader,这两种ClassLoader通过读取dex再调用一些native的方法,可以加载程序运行时所需要的类。
在Android Sdk中的PathClassLoader和DexClassLoader无法看到源码,所以想要看具体源码实现,可以去看android_libcore的源码
DexClassLoader和PathClassLoader的异同
public class PathClassLoader extends BaseDexClassLoader {
public PathClassLoader(String dexPath, ClassLoader parent) {
super(dexPath, null, null, parent);
}
public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
super(dexPath, null, librarySearchPath, parent);
}
}
public class DexClassLoader extends BaseDexClassLoader {
public DexClassLoader(String dexPath, String optimizedDirectory,
String librarySearchPath, ClassLoader parent) {
super(dexPath, new File(optimizedDirectory), librarySearchPath, parent);
}
}
}
从上面看出,两种ClassLoader在实现上只是构造方法不同:PathClassLoader在调用父类构造方法时optimizedDirectory传入为null;DexClassLoader却传了一个new File(optimizedDirectory)进去。
optimizedDirectory是什么
/**
* Constructs an instance.
*
* @param dexPath the list of jar/apk files containing classes and
* resources, delimited by {@code File.pathSeparator}, which
* defaults to {@code ":"} on Android
* @param optimizedDirectory directory where optimized dex files
* should be written; may be {@code null}
* @param librarySearchPath the list of directories containing native
* libraries, delimited by {@code File.pathSeparator}; may be
* {@code null}
* @param parent the parent class loader
*/
public BaseDexClassLoader(String dexPath, File optimizedDirectory,
String librarySearchPath, ClassLoader parent) {
super(parent);
this.pathList = new DexPathList(this, dexPath, librarySearchPath, optimizedDirectory);
}
注释中说optimizedDirectory是optimized dex的路径,也就是传说中的odex。也就是说,我们可以将自己指定的odex路径作为参数传入DexClassLoader,odex中的相关类将被加载。但是PathClassLoader在构造方法中,已经将optimizedDirectory写死为null了,所以PathClassLoader从原则上是无法加载用户指定的odex的。
BUT!!!,在BaseDexClassLoader中有一个方法: