JVM的双亲委派模型,大白话透彻讲解

一.类与类加载器.
  • 一个类的唯一性要由加载该类的类加载器和全限定类名一起确定,换句话说,即使,即使全限定类名一样,使用不同的类加载器加载,也会是两个不同的类.为什么要这样设计?思考一个问题,如果你自定义的类和JAVA程序中某个类名相同,那么JVM应该使用哪个类?
二.几种类加载器.
  1. 启动类加载器 Bootstrap ClassLoader:加载JAVA_HOME下的lib下面的类库,是JVM的一部分,使用C++实现.启动类加载器无法被Java程序直接使用.
  2. 扩展类加载器:Extension ClassLoader:加载JAVA_HOME下的lib/ext下面所有的类库,开发者可以直接使用扩展类加载器.
  3. 应用程序类加载器:Application ClassLoader,也叫做系统类加载器,如果程序中没有自己定义类加载器,那么一般情况下该加载器就作为程序中的默认加载器.
三.双亲委派模型.
  • 很好理解,如果一个类加载器收到了类加载的请求,他首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当类加载器反馈自己无法完成这个加载请求(他的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载,然后把加载对象再一级一级返回.

如下图所示:

JVM的双亲委派模型,大白话透彻讲解_第1张图片

四.双亲委派模型的好处.
  1. 使得Java类随着它的类加载器一起具备了一种带有优先级层次的关系,比如说例如类java.lang.Object,它存放在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此java.lang.Object类在程序的各种类加载器环境中都是同一个类
五.有时候需要破坏双亲委派模型.
  • 比如JDBC,先说一下SPI(Service Provider Interface),这玩意和API不一样,它是面向拓展的,也就是我定义了这个SPI,具体如何实现由扩展者实现。我就是定了个规矩。

  • JDBC就是如此,在里面定义了这个SPI,那mysql有mysql的jdbc实现,oracle有oracle的jdbc实现,那我就需要加载各自的具体的实现类,不能向上委托,就违反了双亲委派模型.

  • 说的大白话一些,就是什么时候需要设置类加载器去破坏双亲委派模型呢?就是当你想加载自定义类,不想去加载JVM中的默认类的时候(你的自定义类可能和JVM中默认类有同名的情况)

那么具体怎么设置呢?

  • 通过线程上下文类加载器,调用Thread.currentThread.setContextClassLoader(类加载器),默认情况就是应用程序类加载器

你可能感兴趣的:(Java,java,jvm,jdbc)