赞
踩
类加载 --> 验证 --> 准备 --> 解析 --> 初始化 --> 使用 --> 卸载
七个阶段,其中验证、准备、解析这三个部分统称为连接hello()
方法,hello是符号引用,地址值是直接引用双亲委托机制即父委托机制,指多个类加载器之间存在父子关系,当一个类加载的过程中,它首先不回去加载,而是委托给父类去加载,父类又委托给父类,因此所有的类加载都会委托给顶层的父类即BoostrapClassLoader
进行加载。
如果父类无法完成这个加载请求,子加载器才会尝试自己去加载。
使用双亲委托机制,Java类随着它的类加载器一起具备类一种带优先级的层次关系。通过这种层次关系,可以避免类的重复加载,可以避免核心类被不同的类加载器加载到内存中造成冲突和混乱,保证了Java核心库的安全。
<JAVA_HOME>/lib
目录下的核心库sum.misc.Launcher#ExtClassLoader
<JAVA_HOME>/lib/ext
目录下的扩展类,如swing系列、内置js引擎、xml解析器sum.misc.Launcher$AppClassLoader
流程说明
当有一个Class文件要被加载时,暂时不考虑我们自定义类加载器。最先从AppClassLoader中检查是否加载过(每个类加载器都有自己的加载缓存,当一个类被加载了以后就会放入缓存,等下次加载的时候就可以直接返回了),如果有加载过无需再加载,否则会获取父加载器,再调用父加载器的loadClass()
检查是否加载过,同理类似递归调用;直到BootstrapClassLoder检查知否加载过,如果没有加载过则会下沉到子加载器处理。这时候如果子加载器不能加载则抛出ClassNotFoundException
异常。
双亲委托机制的代码流程在java.lang.ClassLoader#loadClass()
中
protected Class<?> loadClass(String name, boolean resolve) { Class<?> c = findLoadedClass(name); //检查类是否被加载过 if (c == null) { try { //如果没有加载,调用父类的加载器 if (parent != null) { c = parent.loadClass(name, false); } else { //父类加载器为空,使用默认的 启动类加载器 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { } if (c == null) { //父类加载器无法加载,则调用自身的findClass()进行类加载 c = findClass(name); } } return c; }
Java中的ClassLoader可以加载jar文件和Class文件,这一点再Android中不适用,Android加载的是dex文件,所以在需要重新设计ClassLoader相关类。
Androd中的ClassLoader和Java的ClassLoader相似,也分为两种类型,分别是系统ClassLoader和自定义ClassLoader。系统ClassLoader包含:BootClassLoader、PathClassLoader和DexClassLoader。
PathClassLoader和DexClassLoader在Android8.0之后完全一样
常用命令:
dx --dex --no-strict --ouput <生成的dex文件名> <class文件包名>
例子:
./dx --dex --no-strict --output /Users/limengge/dev/fixed-01.dex /Users/limengge/dev/fixed/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。