类加载器与双亲委派机制
1.什么是类加载器
就是将我们的字节码(class文件)读取到JVM内存中。
2.读取class文件来源
1:本地磁盘文件 java代码变为的class文件
2:通过网络下载的class文件
3:War、jar 解压的class文件
4:从专门的数据库中读取的class文件
5:使用 java cglib、动态代理生成的代理类class文件
3.类加载的分类
1.启动(Bootstrap)类加载器:加载JVM自身工作需要的类,它由JVM自己实现。它会加载$JAVA_HOME/jre/lib下的文件 底层是C语言实现
2.扩展(Extension)类加载器:它是JVM的一部分,由sun.misc.LauncherExtClassLoader实现,他会加载ExtClassLoader实现,他会加载ExtClassLoader实现,他会加载JAVA_HOME/jre/lib/ext目录中的文件(或由System.getProperty(“java.ext.dirs”)所指定的文件)。 底层是Java实现
3.(应用)AppClassLoader 类加载器:应用类加载器,我们工作中接触最多的也是这个类加载器,它由sun.misc.Launcher$AppClassLoader实现。他加载我们工程目录classpath下的class及jar包 底层是java实现
4.自定义类加载器: 也就是用户自己定义的类加载器
类加载器执行顺序图:
类加载器分类职能图:
4.那些操作会触发类加载操作
类的主动使用:
1. 调用类的静态方法
2. invokeStatic 调用静态方法
3. Main
4. New
5. Class.formname
6. 子类初始化一定会初始化父类 初始化一个类,那么一定会触发类加载器 但是类加载器加载了该类,但是该类不一定初始化。
5.类加载器的双亲委派机制
首先在我们类加载器分为四种 自定义类加载器、应用类加载器、扩展类加载器、启动类加载器。
当一个类加载器收到请求之后,首先会依次向上查找到最顶层类加载器(启动类加载器),依次向下加载class文件,如果已经加载到class文件,子加载器不会加继续加载该class文件。
6.双亲委派机制的好处
依次向上查找最顶端启动类加载器读取class文件,只要启动类加载器读取成功之后,以后不会再扩展、应用类加载器读取。
目的:就是为了防御开发者定义的类与jdk定义源码类产生冲突问题,保证该类在内存中的唯一性。
7.ClassLoader源码解读
8.默认当前线程关联的是应用类加载器(Launcher类)
9.如何破坏双亲委派原则
双亲委派代码在loadclass方法中,只需要绕开loadclass方法即可。
1:自定义类加载器 重写loadclass方法。
2:Spi机制绕开loadclass方法,当前线程设置关联类加载器。
Spi机制绕开loadclass方法,核心先找到当前类的类加载器目录下是否有该Spi机制对应的配置文件,如果没有的情况下则不会进行初始化该类,会报错。
10.SPI机制介绍
Spi机制加载第三方扩展的Jar包类初始化,对我们接口的子类实现初始化。
例如:java-JDBC 使用mysql驱动Jar包(初始化Driver类)、dubbo中RPC调用的时候。
SPI命名规范:
文件夹命名:存在在项目中 Resoucres 新建META-INF.services
文件命名:必须是接口类的完全限定名称(需要初始化类的接口名称)
JVM 虚拟机内存空间图: