类加载过程与双亲委派机制以及如何绕过双亲委派直接加载

1.概述

我们都知道Java代码会被编译成class文件,在class文件中描述了该类的各种信息,class类最终需要被加载到虚拟机中才能运行和使用。

虚拟机把Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成虚拟机可以直接使用的Java类型,这就是虚拟机的类加载机制。

2.类加载过程

加载的过程是通过类加载器实现的。

 

 

 

3.类加载器的分类

类加载器分为系统级别和用户级别:

系统级别的类加载器有:

1、启动类加载器(底层使用C++实现)

2、扩展类加载器(底层使用java实现,是ClassLoader的子类)

3、应用程序类加载器(底层使用java实现,是ClassLoader的子类)

用户级别的类加载器我们统一称为自定义类加载器。

3.1 启动类加载器

首先我们来看看启动类加载器加载了哪些类,启动类加载器负责加载sun.boot.class.path:

通过上面的代码我们可以获取到启动类加载器所加载的类

3.2 拓展类加载器

扩展类加载器加载负责加载java.ext.dirs,我们同样写一段代码去加载它:

可以看到,除了加载了JDK目录下的ext外,还加载了Sun目录下的ext

 

3.3 应用程序类加载器

最后是应用类加载器,它负责加载java.class.path:

它负责加载工程目录下classpath下的class以及jar包。

4.双亲委派模型

所谓双亲委派模型,就是指一个类接收到类加载请求后,会把这个请求依次传递给父类加载器(如果还有的话),如果顶层的父类加载器可以加载,就成功返回,如果无法加载,再依次给子加载器去加载。

我们先通过代码来看一下类加载器的层级结构:

编写一个类,依次输出这个类的类加载器,父类加载器,父类的父类加载器

可以看到首先是应用程序类加载器,它的父类是扩展类加载器,扩展类加载器的父类输出了一个null,这个null会去调用启动类加载器。如果你不信,我们看源码:ClassLoader类

接着从父类加载器往下调用findClass,如果可以加载,就直接返回class,如果不能加载,就依次向下。如果到了自定义加载器还是无法被加载,就会抛出ClassNotFound异常。

下面流程图来展示双亲委派模型的全过程:

双亲委派模型保证了Java程序的稳定运行,可以避免类的重复加载,也保证了 Java 的核心 API 不被篡改。
5.破坏双亲委派
双亲委派模型并不是绝对的,spi机制就可以打破双亲委派模型。
同时,我们也可以通过继承ClassLoader类,重写loadClass方法打破双亲委派模型。
//loadClass 源码
protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    // 这一块实现了双亲委派的机制
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
                ...
        }
    }

 

posted @ 2022-09-08 17:14  蜗壳吃虾米  阅读(351)  评论(0)    收藏  举报