JVM-双亲委派

1.首先我们要了解类加载的过程,如图:

JVM-双亲委派

一句话概括:将我们的class文件读取到内存中, 类加载器加载我们的class文件,并且经历过验证、准备、解析,在初始化我们该类。初始化一个类,那么一定会触发类加载器。

 

2.类加载器的分类有哪些?

启动类加载器(Bootstrap):加载JVM自身工作需要的类,它由JVM自己实现。它会加载$JAVA_HOME/jre/lib下的文件 底层是C语言实现

扩展类加载器(Extension):它是JVM的一部分,由sun.misc.LauncherExtClassLoader实现,他会加载ExtClassLoader实现,他会加载ExtClassLoader实现,他会加载JAVA_HOME/jre/lib/ext目录中的文件(或由System.getProperty(“java.ext.dirs”)所指定的文件)。 底层是Java实现

应用类加载器(App):应用类加载器,我们工作中接触最多的也是这个类加载器,它由sun.misc.Launcher$AppClassLoader实现。他加载我们工程目录classpath下的class及jar包  底层是java实现

 

3.什么是双亲委派机制?

首先在我们类加载器分为四种 自定义类加载器、应用类加载器、扩展类加载器、启动类加载器。

当一个类加载器收到请求之后,首先会依次向上查找到最顶层类加载器(启动类加载器),依次向下加载class文件,如果已经加载到class文件,子加载器不会加继续加载该class文件。

JVM-双亲委派

 

4.双亲委派原则有什么作用?

目的就是为了防御开发者为定义的类与jdk定义源码类产生冲突问题,保证该类在内存中的唯一性。用白话文来说,比如说你写Java用了String类,你怎么保证你用的那个String类就是JDK里提供的那个String类呢?答案是对于JDK基础类,JDK要用特殊的ClassLoader来保证在正确的位置加载。

 

5.是否能破坏双亲委派原则呢?

双亲委派这个模式虽然“安全“,但是损失了一丢丢灵活性。就比如java.sql.Driver这个东西。JDK只能提供一个规范接口,而不能提供实现。提供实现的是实际的数据库提供商。提供商的库总不能放JDK目录里吧。

所以在jdk1.6高出了个SPI,开发者要做的就是定制一个实现类,在 META-INF/services 中注册实现类信息,以供核心类库使用。

JVM-双亲委派

SPI 是如何打破双亲委派模型的呢?

java.util.ServiceLoader#load(java.lang.Class<S>)JVM-双亲委派JVM-双亲委派JVM-双亲委派

核心先找到当前的类加载器,然后查看该类加载器下有没有spi机制对应的配置文件(fullName就是在META-INF/services/目录下的文件名), 如果没的情况下,则不会初始化该类。