JavaDriver JavaDriver
首页
  • 基础
  • 并发
  • JVM
  • 设计模式
  • 计算机网络
  • 操作系统
  • 数据结构
  • 算法
  • MYSQL
  • REDIS
  • Netty
  • Kafka
系统设计
非技术
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

YoungAnn

西二旗Java老司机一枚 致力于社会主义添砖Java
首页
  • 基础
  • 并发
  • JVM
  • 设计模式
  • 计算机网络
  • 操作系统
  • 数据结构
  • 算法
  • MYSQL
  • REDIS
  • Netty
  • Kafka
系统设计
非技术
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 基础

    • Java 异常有哪些类型?
    • HashMap 与 ConcurrentHashMap 的实现原理是怎样的?
    • Java 中接口和抽象类的区别
    • 为什么重写 equals 必须重写 hashcode ?
    • == 和 equals() 的区别?
    • String,StringBuffer,StringBuilder 之间有什么区别?
    • 简述 ArrayList 与 LinkedList 的底层实现以及常见操作的时间复杂度
    • 简述 BIO, NIO, AIO 的区别
    • 在一个静态方法内调用一个非静态成员为什么是非法的?
    • 简述 Java 的反射机制及其应用场景
    • Java 类的加载流程是怎样的?
    • 什么是双亲委派机制?
      • 什么是双亲委派机制?
    • Java 中 sleep() 与 wait() 的区别
    • 简述 Java 中 final 关键字的作用
    • String 类能不能被继承?为什么?
    • Java 缓冲流 buffer 的用途和原理是什么?
    • 简述动态代理与静态代理
    • 阻塞队列都有哪几种,有什么区别?
    • 简述 HashSet 实现原理
  • 并发

  • JVM

  • 设计模式

  • Java相关
  • 基础
YoungAnn
2022-04-04
目录

什么是双亲委派机制?

# 什么是双亲委派机制?

双亲委派机制是指当一个类加载器收到一个类加载请求时,该类加载器首先会把请求委派给父类加载器。

加载器 加载哪些类
bootstrap classloader 加载jre/lib/rt.jar
extension classloader jre/lib/ext/*.jar
application classloader 加载应用程序目录
自定义ClassLoader 定制化加载

再来读一下java.lang.ClassLoader这段代码 是不是通透了许多?

    public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }
    //              -----??-----
    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
            // 首先,检查是否已经被类加载器加载过
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    // 存在父加载器,递归的交由父加载器
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        // 直到最上面的Bootstrap类加载器
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
 
                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    c = findClass(name);
                }
            }
            return c;
    }


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

Q1:使用双亲委派有什么好处?
A:双亲委派机制能保证多加载器加载某个类时,最终都是由一个加载器加载,确保最终加载结果相同。
考虑到安全因素。
假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。

Q2:什么场景需要破坏双亲委派?
双亲委派模型很好的解决了各个类加载器的基础类的统一问题(越基础的类由越上层的加载器进行加载)
基础类之所以称为“基础”,是因为它们总是作为被用户代码调用的API 但没有绝对,如果基础类调用会用户的代码怎么办呢? 比如JDBC驱动加载。 这种场景就需要用到SPI机制,是不符合双亲委派的。

Q3:JDBC、Tomcat中为什么要破坏双亲委派模型
A:JDBC
先来回顾一下JDBC的用法

String url = "jdbc:mysql:///consult?serverTimezone=UTC";
String user = "root";
String password = "root";

Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, user, password);
1
2
3
4
5
6

DriverManager 类中要加载各个实现了Driver接口的类,然后进行管理,DriverManager位于 JAVA_HOME中jre/lib/rt.jar 包,由BootStrap类加载器加载.
JDBC的Driver接口定义在JDK中,其实现由各个数据库的服务商来提供,比如MySQL驱动包位于服务商MySQL提供的 Jar 中包含Driver的实现,按照双亲委派模型应该由application classloader加载
实际上却是由BootStrap类加载器加载。
这是因为:根据类加载机制,当被装载的类引用了另外一个类的时候,虚拟机就会使用装载第一个类的类装载器装载被引用的类。
这就破坏了双亲委派模型。

Tomcat
每个webappClassLoader加载自己目录下的class文件

Tomcat支持部署多个Web应用,多个Web应用可能使用不同版本的JDK、也可能在应用内部定义全限定名一样的类,所以要做到应用隔离。

编辑 (opens new window)
上次更新: 2022/05/19, 21:26:01
Java 类的加载流程是怎样的?
Java 中 sleep() 与 wait() 的区别

← Java 类的加载流程是怎样的? Java 中 sleep() 与 wait() 的区别→

最近更新
01
电商-商品系统设计
12-17
02
关于如何写OKR
12-09
03
对事不对人 vs 对人不对事
12-09
更多文章>
Theme by Vdoing | Copyright © 2022-2023 YoungAnnn | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式