对于虚拟机,只有两种不同的类加载器: 具体划分,如下: 应用程序由这三种类加载器互相配合进行加载的,如果有必须,还可以加入自己定义的类加载器。这些类加载器之间的关系一般如下图 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完全这个加载请求时(查看该类是否是在自己的加载范围),子加载器才会尝试自己去加载。 双亲委派的好处: 安全性:使用双亲委派模型来组织类加载器之间的关系,有一个很明显的好处,就是Java类随着它的类加载器(说白了,就是它所在的目录)一起具备了一种带有优先级的层次关系,这对于保证Java程序的稳定运作很重要。例如,类java.lang.Object类存放在JDK\jre\lib下的rt.jar之中,因此无论是哪个类加载器要加载此类,最终都会委派给启动类加载器进行加载,这边保证了Object类在程序中的各种类加载器中都是同一个类,可以防止java核心类被篡改。 避免重复加载:当使用了双亲委派机制后,当一个类已经被上级类加载器加载后,下级类加载器就不会出现重复加载的情况。 Class.getClassLoader().getResource(String path)中,path不能以'/'开头,path是指类加载器的加载范围,在资源加载的过程中,使用的逐级向上委托的形式加载的,'/'表示Boot ClassLoader,类加载器中的加载范围,因为这个类加载器是C++实现的,所以加载范围为null。如下所示:参考 Class.getResource和Class.getResourceAsStream在使用时,路径选择上是一样的。 ClassLoader 代表的是用来加载其他类的类,任何一个class都包含对加载这个class的类加载器(ClassLoader)的引用,所以其加载资源一定是绝对路径,且不能以‘/’开头 Class.getClassLoader().getResource和Class.getClassLoader().getResourceAsStream在使用时,路径选择上也是一样的。 https://juejin.cn/post/6844904159993397262加载器

上图中展示的类加载器之间的层次关系,就称为类加载器的双亲委派模型(Parents Delegation Model)。双亲委派模型要求除了顶层的启动类加载器之外,其余的类加载器都应当有自己的父类加载器。这里的类加载器之间的父子关系一般不会以继承的关系来实现,而是使用组合关系来复用父加载器的代码。双亲委派模型
使用场景
public class Test
{
public static void main(String[] args)
{
System.out.println(Test.class.getClassLoader().getResource(""));
System.out.println(Test.class.getClassLoader().getResource("/"));
}
}
Class.getResource和ClassLoader.getResource
Class.getResource(String path)
Class.getClassLoader().getResource(String path)
参考