JVM类加载器和双亲委派机制

315 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

背景:最近在看jvm的东西,整理一波jvm类加载器和双亲委派机制知识点

类加载器分类:

引导类加载器:bootstrap Class Loader
自定义类加载器:继承ClassLoader的类
jvm支持两种类型的类型加载器,分别为引导类加载器,自定义类(除引导类加载器都是自定义类加载器)    

类加载器细分(从最上层到下层顺序)

1.bootstrap Class Loader(引导类加载器,c++实现)
java核心类库(String Integer 。。。)都是使用引导类加载器进行加载
2.Extension Class loader (扩展类加载器,自定义类加载器)
用户自定义的类默认使用系统类加载器进行加载
3.System Class loader(系统类加载器,自定义类加载器)
4.User Defined Class Loader(用户自定义加载器,自定义类加载器)
各个类加载器之间没有继承的概念,是包含的概念,像文件夹系统一样。
1.引导类加载器(启动类加载器,Bootstrap ClassLoader)
这个类加载器使用c/c++语言实现的,嵌套在jvm内部
它用来加载Java的核心库(JAVA_HOME/jre/lib/ret.jar,resource.jar,sun.boot.class.path路径下的内容),用于提供jvm自身需要的类
加载扩展类和应用程序类加载器,并制定为他们的父类加载器(因为这两类加载器也是Java核心库中的类,所以需要bootstratp classloader来加载)
没有父类加载器,(最上层)
出于安全考虑,Bootstrap ClassLoader类加载器只加载包名为java,javax,sun等开头的类
2.扩展类加载器(Extension ClassLoader)
1.java语言编写,sun.misc.launcher$ExtClassLoader
2.派生于ClassLoader类
3.父类加载器为启动类加载器
4.从java.ext.dirs系统属性制定的目录中加载类库,或从JDK的安装目录的jre/lib/ext子目录(扩展目录)下加载类库。如果用户建的jar放在此目录下,也会自动由扩展类加载器加载。
3.应用程序类加载器(系统类加载器 AppClassLoader)
1.java语言编写,sun.misc.launcher$AppClassLoader
2.父类加载器为ExtensionClassLoader
3.负责加载环境变量classpath或系统属性java.class.path指定路径下的类库
4.该加载器是程序中默认的类加载器,一般来说,java应用的类都是由它来加载的
5.获取该类加载器ClassLoader::getSystemClassLoader()

Java虚拟机对class文件采用的是按需加载方式,而加载某个类的class文件时,java虚拟机采用的是双亲委派模式。

双亲委派机制

工作原理

1.如果一个类加载器收到了加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行
2.如果父加载器还存在其父类加载器,则继续向上层委托,依次递归,请求最终达到顶层的bootstrapClassLoader(引导类加载器)
3.如果父类加载器可以加载,就成功返回,如果不能加载,子类加载器才会尝试自己去加载,这就是双亲委派机制。

优势

1.避免类被重复加载
2.保护程序安全,防止核心api被随意篡改。(沙箱安全机制)

在jvm中表示两个类是否为同一个类的条件

1.类的完整类名一致,包括包名
2.加载这个类的ClassLoader必须相同
3.如果一个类是由自定义加载器加载的,那么jvm会将这个加载器的引用保存到该类的类型信息中存到方法区。当解析一个类型到另一个类型的引用的时候,jvm会保证两个类型的类加载器是相同的。