java语言中支持4种类加载器:
-
Bootstrap ClassLoader 启动类加载器
-
Extention ClassLoader 标准扩展类加载器
-
Application ClassLoader 应用类加载器
-
User ClassLoader 用户自定义类加载器
当一个类收到了一个类加载的请求的时候,他不会直接去加载指定的类,而是把这个请求委托给自己的父加载器去加载,只有父加载器无法加载的时候,才会由当前加载器去负责类的加载。
这四种类加载器,各有各的职责:
-
Bootstrap ClassLoader ,主要负责加载Java核心类库,%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等。
-
Extention ClassLoader,主要负责加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件。
-
Application ClassLoader ,主要负责加载当前应用的classpath下的所有类
-
User ClassLoader , 用户自定义的类加载器,可加载指定路径的class文件
也就是说,一个用户自定义的类,如com.test.Test是无论如何也不会被Bootstrap和Extention加载器加载的。
通过委派的方式,可以避免类的重复加载,当父加载器已经加载过一个类的时候,子加载器不会再重新加载这个类。
而且通过双亲委派的方式,还保证了安全性,因为Bootstrap ClassLoader在加载的时候,只会加载JAVA_HOME中的jar包里面的类,如java.lang.Integer,这个类是不会被随意替换的,除非有人跑到你的机器上,破坏你的JDK。
实现双亲委派的代码就在java.lang.ClassLoader类的loadClass方法中,大概逻辑:
-
先检查类是否被加载过
-
如果没有加载则调用父加载器的loadClass方法进行加载
-
如果父加载器为空则默认使用启动类加载器(bootstrapclass loader)作为父加载器
-
如果父加载器加载失败,抛出ClassNotFoundException异常后,在调用自己的findClass方法进行加载。
网友评论