什么是类加载器
将我们class文件读取到内存中。
Class文件读取来源
- 本地磁盘文件java代码变为的class文件
- 通过网络下载的class文件
- War、jar解压的class文件
- 从专门的数据库中读取的class文件
- 使用javacglib、动态代理生成的代理类class文件
类加载器加载的过程
类加载器的分类
- 启动类(Bootstrap类加载器):加载JVM自身工作需要的类,它由JVM自己实现,它会加载$JAVA_HOME/jre/lib下的文件,底层是C语言实现
- 扩展(Extentsion)类加载器:它是JVM的一部分,由sun.misc.LaucherExtClassLoader实现,他会加载ExtClassLoader实现,会加载JAVA_HOME/jre/lib/ext目录中的文件,底层是Java实现
- (应用)AppClassLoader类加载器:应用类加载器,它由sun.misc.Launcher$AppClassLoader实现,它加载我们工程目录classpatch下的class及jar包,底层是java实现
- 自定义了加载器
ClassLoader类加载器双亲委派机制
当我们类加载器收到一个请求的时候,首先会依次向上查找最顶层没有父类的类加载器,依次向下读取class文件,如果该类加载器已经读取到class文件的时候,下面的加载器不会继续读取。
好处
防御开发者定义包名和类名,与java虚拟机定义完全一样,保证内存中只有一个。
Spi机制的原理
全称是Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的API,可以用来启用框架扩展和替换组件。
如何破坏双亲委派机制
通过指定线程的类加载器
package com.mayikt;
import com.mayikt.service.IMemberService;
import java.util.ServiceLoader;
/**
* @Description:
* @Author: ChenYi
* @Date: 2020/08/13 08:30
**/
public class Test004 {
public static void main(String[] args) {
//指定线程的类加载器不是应用类加载器
Thread.currentThread().setContextClassLoader(Test004.class.getClassLoader().getParent());
ServiceLoader<IMemberService> load = ServiceLoader.load(IMemberService.class);
load.forEach((t) -> {
System.out.println(t);
});
}
}
参考:蚂蚁课堂