JVM学习 — 双亲委派

本文介绍了Java的双亲委派模型,详细讲解了类加载器的工作原理,包括Bootstrap、Extension和AppClassLoader的职责。讨论了Tomcat如何通过自定义类加载器实现Web应用隔离,以及JDBC如何在特定情况下“破坏”双亲委派模型。最后,探讨了模块化技术如JDK9中的模块系统对类加载机制的影响。
摘要由CSDN通过智能技术生成

双亲委派

  • 类加载器

  • 双亲委派模型

  • 破坏双亲委派模型

    • Tomcat
    • JDBC
  • 模块化技术与类加载机制

类加载器

image-20220317202632609

Class 文件是通过类加载器加载到虚拟机中的,这个动作在虚拟机外部实现,以便让应用程序自己决定如何去获取所需的类,实现这个动作的代码被称为“类加载器”。

对于任意一个类,必须由加载它的类加载器和这个类本身一起共同确立其在java虚拟机中的唯一性。每一个类加载器都拥有一个独立的类名称空间。

一个Tomcat可以运行多个war包,说明一个Tomcat 可以运行多个Web应用,万一这些应用中有类的全限定名一样,但是具体实现不一样,这样的话Tomcat 如何保证不冲突?

Tomcat 给每个Web应用创建一个类加载器实例(WebAppClassLoader), 该加载器重写了 loadClass 方法,优先加载当前应用目录下的类,如果找不到,再往上找。这样的话就做到了Web 应用的隔离。Tomcat破坏双亲委派下面再详细介绍。

什么情况下需要自定义类加载器

1️⃣ 隔离加载类。在某些框架内进行中间件与应用的模块隔离,把类加载器到不同的环境。比如,阿里内某容器框架通过自定义类加载器确保应用中依赖的 jar 包不会影响到中间件运行时使用的 jar 包。

2️⃣ 修改类加载方式。类的加载模型并非强制,除了 Bootstrap 外,其他的加载并非一定要引入,或者根据实际情况在某个时间点进行按需的动态加载。

3️⃣ 扩展加载源。比如从数据库、网络,甚至是电视机顶盒进行加载。

4️⃣ 防止源码泄露。Java 代码容易被编译和篡改,可以进行编译加密。那么类加载器也需要自定义,还原加密的字节码。

双亲委派模型

双亲委派模型

上图每个加载器都有对应的加载搜索范围

  1. Bootstrap ClassLoader:由底层的c++实现,负责在虚拟机启动时加载Jdk核心类库(如:rt.jar、resources.jar、charsets.jar等)以及加载后两个类加载器。这个ClassLoader完全是JVM自己控制的,需要加载哪个类,怎么加载都是由JVM自己控制,别人也访问不到这个类。
  2. Extension ClassLoader:是一个普通的Java类,继承自ClassLoader类,负责加载{JAVA_HOME}/jre/lib/ext/目录下的所有jar包。
  3. AppClassLoader:负责加载应用程序classpath目录下的所有jar和class文件。

​ 所谓双亲委派是指每次收到类加载请求时,先将请求委派给父类加载器完成(所有加载请求最终会委派到顶层的Bootstrap ClassLoader加载器中),如果父类加载器无法完成这个加载(该加载器的搜索范围中没有找到对应的类),子类尝试自己加载, 如果都没加载到,则会抛出 ClassNotFoundException 异常。(类加载器加载完类会放入自己的缓存中,类加载器在加载类时先应该看自己的缓存中有没有,没有的话再进行双亲委派)。

为什么需要双亲委派?好处是什么?

​ 这种机制使得类加载器之间有严格的层次关系,也使得java类有了层次关系。

​ 可以避免重复加载,当父类加载器已经加载了该类的时候,就没有必要 ClassLoader 再加载一次。

安全性:有效的防止java 核心 api 被篡改。如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义的类型。可以避免我们自己写的类和 JDK 自带的核心类发生冲突。

双亲委派是如何实现的?

双亲委派模型对于保证Java程序的稳定运作很重要,但它的实现并不复杂。

实现双亲委派的代码都集中在java.lang.ClassLoader的loadClass()方法之中

protected Class<?> loadClass(String name, boolean resolve)
  throws ClassNotFoundException
{
   
  synchronized (getClassLoadingLock(name)) {
   
    // 首先检查是否已经加载过了
    Class<?> c = fin
JVM中的双亲委派机制是一种类加载机制,它规定了在Java中一个类被加载时如何进行类加载器的选择。根据这个机制,当一个类需要被加载时,首先会由类加载器ClassLoader检查是否已经加载过该类,如果是,则直接返回已经加载过的类;如果不是,则将该请求委派给父类加载器去加载。这样的过程会一直向上委派,直到达到顶层的引导类加载器(Bootstrap ClassLoader)。引用 引用中提到,并不是所有的类加载器都采用双亲委派机制。Java虚拟机规范并没有强制要求使用双亲委派机制,只是建议使用。实际上,一些类加载器可能会采用不同的加载顺序,例如Tomcat服务器类加载器就是采用代理模式,首先尝试自己去加载某个类,如果找不到再代理给父类加载器。 引用中提到,引导类加载器(Bootstrap ClassLoader)是最早开始工作的类加载器,负责加载JVM的核心类库,例如java.lang.*包中的类。这些类在JVM启动时就已经被加载到内存中。 综上所述,JVM双亲委派机制是一种类加载机制,它通过类加载器的委派方式来加载类,首先检查是否已经加载过该类,如果没有则委派给父类加载器去加载,直到达到顶层的引导类加载器。不过,并不是所有的类加载器都采用该机制,一些类加载器可能会采用不同的加载顺序。引用<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [JVM-双亲委派机制](https://blog.csdn.net/m0_51608444/article/details/125835862)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [jvm-双亲委派机制](https://blog.csdn.net/y08144013/article/details/130724858)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值