原理图:

代码实现:

这段代码的意思是:如果当前类加载器还有父类,就委托父类进行类加载,这个过程一直持续到BootstrapClassLoader这个类中,如果没有则报错。如果某一个父类中有,则加载到内存中,同时findLoadedClass就能够得到加载后的class,直接跳过父类加载器以外的加载器。

回答:

JDK有三中类加载器:用来加载核心类库的引导类加载器(BootStrap ClassLoader)、用来加载拓展类库的拓展类加载器(Extension ClassLoader)、用来加载类路径下文件的程序类加载器(App ClassLoader),当然我们也可以自己通过继承ClassLoader实现Custom ClassLoader。

双亲委派机制就是当JVM收到一个类加载请求的时候,不会直接让当前类的类加载器加载该类,而是将请求委派给它的上层类加载器,源代码通过一个if else的判断来实现,会先查看它的parent是否为空,如果不为空就交给父类的loadClass方法进行加载,如果为空,就代表请求请求已经到达了最顶层的引导类加载器,然后逐层向下递归加载该类,如果某一层的类加载器找到了就直接加载返回,如果都找不到,那就抛出ClassNotFoundException的异常。

为什么要使用双亲委派机制去加载类呢?

避免自定义的类覆盖核心类库的行为。比如我们可以自定义一个java.lang.Object的类,如果没有双亲委派机制,那么java.lang.Object的类加载请求就可能被App ClassLoader处理,这样就会加载自定义的java.lang.Object从而屏蔽了核心类库中的Object,影响JVM的正常工作。

自定义类加载器的步骤与优势:

自定义类加载器步骤:

* 定义一个类,继承 ClassLoader

* 重写 loadClass 方法

* 实例化 Class 对象

自定义类加载器的优势:

* 类加载器是 Java 语言的一项创新,也是 Java 语言流行的重要原因之一,它最初的设计是为了满足 java applet 的需求而开发出来的

* 高度的灵活性

* 通过自定义类加载器可以实现热部署

* 代码加密

附加:

1.类ClassLoader是一个抽象类,Application ClassLoader和Extension ClassLoader的具体实现类分别是sun.misc.Launcher$AppClassLoader和sun.misc.Launcher$ExtClassLoader,Bootstrap ClassLoader不是由Java实现的,没有对应的类。

 

2.每个Class对象都有一个方法,可以获取实际加载它的ClassLoader,方法是:

public ClassLoader getClassLoader()

 

3.ClassLoader有一个方法,可以获取它的父ClassLoader:

public final ClassLoader getParent()

 

4.如果ClassLoader是Bootstrap ClassLoader,返回值为null

 

5.ClassLoader有一个静态方法,可以获取默认的系统类加载器:

public static ClassLoader getSystemClassLoader()

 

6.ClassLoader中有一个主要方法,用于加载类:

public Class<?> loadClass(String name) throws ClassNotFoundException

 

7.在反射中,有两个方法:

public static Class<?> forName(String className)

public static Class<?> forName(String name, boolean initialize, ClassLoader loader)

第一个方法使用系统类加载器加载。第二个指定ClassLoader,参数initialize表示,加载后,是否执行类的初始化代码(如static语句块),没有指定默认为true