Classloader 类加载机制
JVM把描述类的数据加载到内存里面,并对数据进行校验、解析和初始化,最终变成可以被虚拟机直接使用的class对象。 整个生命周期包括## 7 个阶段。其中准备、验证、解析3个部分统称为连接(Linking)。
- 加载(Loading)
- 验证(Verification)
- 准备(Preparation)
- 解析(Resolution)
- 初始化(Initialization)
- 使用(Using)和卸载(Unloading)

类加载过程
加载。
加载分为三步:
- 通过类的全限定性类名获取该类的二进制流
- 将该二进制流的静态存储结构转为方法区的运行时数据结构
- 在堆中为该类生成一个class对象
验证
验证该class文件中的字节流信息复合虚拟机的要求,不会威胁到jvm的安全
准备
为class对象的静态变量分配内存,初始化其初始值
解析
该阶段主要完成符号引用转化成直接引用
初始化
到了初始化阶段,才开始执行类中定义的java代码;初始化阶段是调用类构造器的过程
类加载器
虚拟机设计团队把加载动作放到 JVM 外部实现,以便让应用程序决定如何获取所需的类,JVM 提供了 3 种类加载器:

启动类加载器(Bootstrap ClassLoader)
用来加载java核心类库,无法被java程序直接引用。负责加载 JAVA_HOME\lib 目录中的,或通过-Xbootclasspath 参数指定路径中的,且被虚拟机认可(按文件名识别,如 rt.jar)的类。
扩展类加载器(Extension ClassLoader)
用来加载java的扩展库,java的虚拟机实现会提供一个扩展库目录,该类加载器在扩展库目录里面查找并加载java类。负责加载 JAVA_HOME\lib\ext 目录中的,或通过 java.ext.dirs 系统变量指定路径中的类库。
应用程序类加载器(Application ClassLoader)
它根据java的类路径来加载类,一般来说,java应用的类都是通过它来加载的。负责加载用户路径(classpath)上的类库。JVM 通过双亲委派模型进行类的加载,当然我们也可以通过继承java.lang.ClassLoader 实现自定义的类加载器。
自定义类加载器(User ClassLoader)
由JAVA语言实现,继承自ClassLoader。
此外我们比较需要知道的几点:
- 一个类是由 jvm 加载是通过类加载器+全限定类名确定唯一性的
- 双亲委派,众所周知,子加载器会尽量委托给父加载器进行加载,父加载器找不到再自己加载
- 线程上下文类加载,为了满足 spi 等需求突破双亲委派机制,当高层类加载器想加载底层类时通过 Thread.contextClassLoader 来获取当前线程的类加载器(往往是底层类加载器)去加载类
双亲委派(重要)
当一个类加载器收到一个类加载的请求,他首先不会尝试自己去加载,而是将这个请求委派给父类加载器去加载,只有父类加载器在自己的搜索范围类查找不到给类时,子加载器才会尝试自己去加载该类。
所有的加载请求都会传送到根加载器去加载,只有当父加载器无法加载时,子类加载器才会去加载:

为什么需要双亲委派模型?
为了防止内存中出现多个相同的字节码。因为如果没有双亲委派的话,用户就可以自己定义一个java.lang.String类,那么就无法保证类的唯一性。
那怎么打破双亲委派模型?
自定义类加载器,继承ClassLoader类,重写loadClass方法和findClass方法。
双亲委派模型的作用
避免类的重复加载 保证Java核心类库的安全
















