Android的classLoader机制
  Android的Dalvik/ART虚拟机如同标准JAVA的JVM虚拟机一样,在运行程序时首先需要将对应的类加载到内存中。因此可以利用这一点,在程序运行时手动加载Class,从而达到代码中动态加载可执行文件的目的。

  在Android系统启动的时候会创建一个Boot类型的ClassLoader实例,用于加载一些系统Framework层级需要的类。由于Android应用里也需要用到一些系统的类,所以APP启动的时候也会把这个Boot类型的ClassLoader传进来。
  此外,APP也有自己的类,这些类保存在APK的dex文件里面,所以APP启动的时候,也会创建一个自己的ClassLoader实例,用于加载自己dex文件中的类。
  下面实际验证看看:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ClassLoader classLoader = getClassLoader();
Log.i("ClassLoader" , "classLoader " + classLoader.toString());
while (classLoader.getParent() != null) {
classLoader = classLoader.getParent();
if (classLoader != null) {
Log.i("ClassLoader", "classLoaderParent " + classLoader.toString());
}
}
}
  输出结果为:
  I/ClassLoader: classLoader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.sunteng.classloader-1/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]]
  I/ClassLoader: classLoaderParent java.lang.BootClassLoader@2d0a3af7
  可以看见有2个Classloader实例,一个是BootClassLoader(系统启动的时候创建的),另一个是PathClassLoader(应用启动时创建的,用于加载当前已安装app里面的类)。
  Android经常使用的是PathClassLoader和DexClassLoader
  PathClassLoader
  官方注释:一个简单的ClassLoader的实现,工作在本地文件系统中的文件和目录的列表上,但不尝试从网络加载类。 Android使用这个类为它的系统类加载器和应用类加载器。
  可以看出,Android是使用这个类作为其系统类和应用类的加载器。并且对于这个类呢,只能去加载已经安装到Android系统中的apk文件。
  DexClassLoader
  官方注释:一个ClassLoader的实现,从.jar和.apk文件内部加载classes.dex。这可以用于执行非安装程序作为已安装应用程序的一部分的代码。
  也是说可以加载比如sd目录下的dex文件,获取到不是已安装app里面的类。
  Android中使用PathClassLoader类作为Android的默认的类加载器,PathClassLoade本身继承自BaseDexClassLoader,BaseDexClassLoader重写了findClass方法,该方法是ClassLoader的核心。
#BaseDexClassLoader
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
Class c = pathList.findClass(name, suppressedExceptions);
if (c == null) {
ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class "" + name + "" on path: " + pathList);
for (Throwable t : suppressedExceptions) {
cnfe.addSuppressed(t);
}
throw cnfe;
}
return c;
}
  看源码可知,BaseDexClassLoader将findClass方法委托给了pathList对象的findClass方法,pathList对象是在BaseDexClassLoader的构造函数中new出来的,它的类型是DexPathList。看下DexPathList.findClass源码是如何做的:
#DexPathList
public Class findClass(String name, List<Throwable> suppressed) {
for (Element element : dexElements) {
DexFile dex = element.dexFile;
if (dex != null) {
Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
if (clazz != null) {
return clazz;
}
}
}
if (dexElementsSuppressedExceptions != null) {
suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
}
return null;
}
#DexFile
public Class loadClassBinaryName(String name, ClassLoader loader) {
return defineClass(name, loader, mCookie);
}
private native static Class defineClass(String name, ClassLoader loader, int cookie);