Android中ClassLoader的种类:
1 BootClassLoader
和java虚拟机中不同的是BootClassLoader是ClassLoader的内部类,由java代码实现而不是c++实现,是Android平台上所有ClassLoader的最终parent,是包内可见,我们没法使用,也不能使用动态加载。
2 URLClassLoader
只能用于加载jar文件,但是由于dalvik
不能直接识别jar,所以在Android中无法使用该加载器。
3 BaseDexClassLoader
PathClassLoader和DexClassLoader都继承自BaseDexClassLoader完成都,这些源码在java/dalvik/system中。
package dalvik.system;
public class BaseDexClassLoader extends ClassLoader {
public BaseDexClassLoader(String dexPath, File optimizedDirectory, String librarySearchPath, ClassLoader parent) {
throw new RuntimeException("Stub!");
}
}
dexpath,指目标类所在的APK,DEX或JAR文件路径(可以是SD卡的路径),类装载器将从该路径中寻找指定的目标类,如果要包含多个路径,路径之间必须使用特定的分隔符分割,特定的分隔符可以从System.getProperty(“path.separtor”)获得,最终做的是将dexPath路径上的文件ODEX优化到内部位置optimizedDirectory,再进行加载的。
File optimizedDirectory,由于dex文件被包含再APK或者Jar文件中,因此再装载目标类之前需要先从APK或者Jar文件中解压出dex文件,该参数就是制定解压缩出的dex文件存放的路径。这也是对apk中dex根据平台进行ODEX优化的过程。其中APK是一个程序压缩包,里面包含dex文件,ODEX优化就是把包里面的执行程序提取出来,就变成ODEX文件,因为你提取出来了,系统第一次启动的时候就不用去解压缩程序压缩包程序,少了一个解压的过程,这样的话系统启动就加快了。为什么说是第一次呢?是因为DEX版本的只有第一次会解压执行程序到/data/dalvik-cache(针对PathClassLoader)或者optimizedDirectory(针对PathClassLoader)或者optimizedDirectory(针对DexClassLoader)目录,之后也是直接读取目录下的dex文件,所以第二次启动就和正常差不多类,当然这知识简单的理解,实际生成的ODEX还有一定的优化作用。ClassLoader只能加载内部存储路径中的dex文件,所以这个路径必须为内部路径。
libraryPath,指目标类中所使用的C/C++库存放的路径。
ClassLoader parent,是指该装载器的父装载器,一般为当前执行类的装载器,例如再Android中以context.getClassLoader()作为父类装载器。
4 PathClassLoader
package dalvik.system;
import java.io.File;
public class PathClassLoader extends BaseDexClassLoader {
public PathClassLoader(String dexPath, ClassLoader parent) {
super((String)null, (File)null, (String)null, (ClassLoader)null);
throw new RuntimeException("Stub!");
}
public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
super((String)null, (File)null, (String)null, (ClassLoader)null);
throw new RuntimeException("Stub!");
}
}
可以看出PathClassLoader没有optimizedDirectory路径,也就是没设置优化后的存放路径,其实optimizedDirectory为null时的默认路径就是/data/dalvik-cache目录。因此,PathClassLoader是用来加载Android系统类和app应用类的。
5 DexClassLoader
package dalvik.system;
import java.io.File;
public class DexClassLoader extends BaseDexClassLoader {
public DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) {
super((String)null, (File)null, (String)null, (ClassLoader)null);
throw new RuntimeException("Stub!");
}
}
DexClassLoader支持加载包含classes.dex的JAR/APK文件,可以是SD卡上的路径。
上面说dalvik不能直接识别JAR,DexClassLoader却可以加载JAR文件,这难道不矛盾吗?其实再BaseDexClassLoader中对”.jar”,”.zip”,”.dex”后缀的文件最后都会生成一个对应的dex文件,所以最终处理的还是dex文件,而URLClassLoader并没有做类似的处理。一般我们都是用这个DexClassLoader来作为动态加载的加载器。
6 InMemoryDexClassLoader
public final class InMemoryDexClassLoader extends BaseDexClassLoader {
public InMemoryDexClassLoader(ByteBuffer[] dexBuffers, ClassLoader parent) {
super((String)null, (File)null, (String)null, (ClassLoader)null);
throw new RuntimeException("Stub!");
}
public InMemoryDexClassLoader(ByteBuffer dexBuffer, ClassLoader parent) {
super((String)null, (File)null, (String)null, (ClassLoader)null);
throw new RuntimeException("Stub!");
}
}
InMemoryDexClassLoader是再API26时新增的类加载器,继承自BaseDexClassLoader。
ByteBuffer数组构造了一个DexPathList,可以用于内存中的DEX文件
7 DelegateLastClassLoader
public final class DelegateLastClassLoader extends PathClassLoader {
public DelegateLastClassLoader(String dexPath, ClassLoader parent) {
super((String)null, (String)null, (ClassLoader)null);
throw new RuntimeException("Stub!");
}
public DelegateLastClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
super((String)null, (String)null, (ClassLoader)null);
throw new RuntimeException("Stub!");
}
}