本文论述有关父母委托模式的几个问题

本文概述了为什么需要父母代理,为什么需要破坏父母代理模型,JdbcTomcat如何破坏父母代理模型,以及如何自定义类加载器的热配置原理

概要

如果一个类加载器收到类加载请求,他会先从自己的缓存中查找是否加载过这个类,如果加载过,他会直接返回。 如果没有加载过,他就不会自己加载。 他将这个请求委托给父类加载器来完成。 每一层也是如此,递归到顶级父类,就像递归一样。

也就是说,Bootstrap ClassLoader在加载完成时返回结果,如果顶级父类加载器无法加载此class,则返回并尝试加载到子类加载器中,如果也找不到最低子类加载器,则返回classnonos

核心思想:其一,自底向上检查类是否已加载;其二,自顶向下尝试加载类

具体加载过程

当AppClassLoader加载class时,它不会首先尝试自己加载类,而是将加载类的请求委托给父类加载器ExtClassLoader完成。 当ExtClassLoader加载类时,它不会首先尝试自己加载类,而是将类加载请求委托给BootStrapClassLoader完成。 如果BootStrapClassLoader加载失败,例如,在%JAVA_HOME%/jre/lib中找不到class,将尝试使用ExtClassLoader加载; 如果ExtClassLoader也加载失败,则使用AppClassLoader加载;如果AppClassLoader也加载失败,则报告异常的ClassNotFoundException。

为什么父母是防止内存中出现多份同样的字节码,安全

例如,如果您自己重写java.lang.Object并将其放入Classpath中,而不是父母要求您直接运行,这是不安全的。 父母委托确保此类仅由顶级Bootstrap Classloader类加载器加载,并确保JVM中只有一个已知良好的java核心类。 如果有多个的话,会很混乱。 例如,同一类instance of可能返回false,因为父类可能不是由同一类加载器加载的Object。

为什么需要破坏父母委托模型Jdbc Jdbc? 为什么要破坏父母委托模式?

以前的用法不破坏父母委托模型,如class.forname (“com.MySQL.CJ.JDBC.driver”)。

从JDBC4.0开始,支持使用spi注册此驱动程序的方法。 更具体地说,指定MySQL jar包的meta-INF/services/Java.SQL.driver文件中当前使用的驱动程序是哪个,并且在使用时不需要手动加载驱动程序

首先,让我们了解一下为什么JDBC需要破坏父母的委托模式。 因为在本机JDBC中,驱动程序本身只是接口,没有具体实现,具体实现由不同的数据库类型实现。 例如,MySQL的mysql-connector-*.jar的驱动程序类是具体实现的。

本机JDBC类放在rt.jar包中,Bootstrap加载器加载该类。 JDBC驱动程序类需要动态加载不同数据库类型的驱动程序类,而mysql-connector-*.jar的驱动程序类是用户自己编写的代码

此时,我们引入了“线程上下文件类加载器”(Thread Context ClassLoader ),以便APP类加载器可以加载原本Bootstrap类加载器需要加载的类。

Tomcat Tomcat为什么要破坏父母的代理模式?

因为一个Tomcat可以部署n个web APP,但每个web APP都有自己的类加载器,不会相互干扰。 例如,web1包含com.test.A.class,web2也包含com.test.A.class。 如果不破坏父母委托模型的话,web1加载后,web2加载时会发生冲突。

虽然只有一组类加载器,但由于有两个重复的类路径,tomcat将其打破了。 他是线程级别的类加载器,具体取决于web APP应用程序。

jdbc4.0等Java spi方式就是其中之一。 热部署的场景将被破坏。 否则,无法实现热部署。 如何破坏父母委托模式重写loadClass方法。 请不要重写findClass方法。 由于loadClass是核心门户,因此将其重写为自定义逻辑可以破坏父母委托模型。

我该如何自定义类加载器只需要继承java.lang.Classloader类以覆盖他的findClass(stringname )方法? 此方法根据参数中指定的类名返回对相应class对象的引用。

热部署原理采用破坏父母委托模型的手段实现热部署。 默认loadClass ) )方法首先查找缓存。 因为您更改class字节码不会热重新加载,所以自定义ClassLoader,消除了查找缓存的部分,直接加载。 也就是说每次都重装。

本文总结介绍了关于父母代理模式的几个问题。