一、类加载的基本流程
加载—>连接(验证—>准备—>解析)—>初始化—>使用—>卸载
加载—在加载阶段,Java虚拟机需要完成以下三件事
1)通过一个类的全限定名来获取定义此类的二进制字节流
2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
验证
可以是文件格式验证、字节码指令验证(方法里面要具体执行的指令)、符号引用验证
准备
就是为类对象中的一些成员分配内存空间,并且进行一个初步的初始化操作,也就是把初始空间设为全0
解析
Java虚拟机将常量池内的符号引用替换为直接引用的过程,也就是初始化常量的过程。
初始化
对静态变量和静态代码块进行初始化操作。
Java虚拟机真正开始执行类中编写的Java程序代码,将主导权移交给应用程序,初始化阶段就是执行类构造器方法的阶段。
二、双亲委派模型
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父加载器去完成,每个层次的类加载器都是如此,因为所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求时,也就是在搜索范围内没有找到所需的类时,子加载器才会尝试自己去完成加载。
执行步骤说明
存在三种类加载器分别是:启动类加载器、扩展类加载器、应用程序类加载器。
1)这三个类加载器之间存在父子关系,但不是继承里面的父类子类关系,而是像链表一样,每个类里面都有一个parent字段,指向父加载器。
2)当在代码中使用某个类的时候,就会触发类加载器,也就是说先触发AppClassLoader,但是AppClassLoader并不会真的开始扫描自己负责的目录,而是先找其父加载器ExtClassLoader,但是ExtClassLoader也不会立即去扫描自己负责的目录,而是也去找其父加载器BootStrapClassLoader
3)到达BootStrapClassLoader后,也不会立即扫描自己负责的目录,也是先找其父加载器,但是BootstrapClassLoader上面已经没有父加载器,因此就去扫描自己负责的目录
4)如果在BootstrapClassLoader中找到了需要的类,就进行加载,就没有其它类加载器的事情了,但是如果没有匹配到合适的类,就会告诉子加载器ExtClassLoader,再从ExtClassLoader所负责的目录中查找所需的类,如果找到就加载,如果未找到就去AppClassLoader所负责的目录区域查找,如果找到就加载,如果到这里还没有找到的话,那就直接抛出ClassNotFoundExcept异常
双亲委派模型的优点:
1)避免重复加载类。
2)使用双亲委派模型可以保证Java的核心API不会被篡改。