类加载器介绍

类加载器

基本介绍(基于jdk1.8)

名称 加载哪的类 说明
BootStrap ClassLoader(启动类加载器) JAVA_HOME/jre/lib 无法直接访问(C++代码书写的)
Extension ClassLoader(扩展类加载器) JAVA_HOME/jre/lib/ext 上级为BookStrap,显示为null
Application ClassLoader(应用程序类加载器) classpath 上级为Extension
自定义类加载 自定义 上级为Application

启动类加载器:

  • -Xbootclasspath表示设置bootclasspath
  • 其中/a:.将当前目录追加至bootclasspath之后
  • 可以用这个方法替换核心类
    • java -Xbootclasspath:<new bootclasspath>{解释:用新路径完全替换掉了原来路径JAVA_HOME/jre/lib}
    • java-Xbootclasspath/a:<追加路径>{解释:不替换原有路径,在原有路径追加路径a}
    • java- Xbootclasspath/p:<追加路径 >{解释:在原有路径上追加}

扩展类加载器

  • 扩展类加载器下的类必须以jar包的方式存在

双亲委派模式

  • 总体思想:委派上级优先做类的加载,上级没有此类,再由本级的类加载器进行加载

  • 执行流程:

    调用本类的classLoad方法:

    先检测该类在本类加载器中是否已加载(findLoadedClass(name)),

    若没有,再判断此加载器是否存在上级。

    若有上级,委派上级:调用上级类加载器的classLoad方法;

    若不存在上级,证明此类加载器为扩展类加载器,则调用findBootstraporNull(name)方法来完成类的查找

    若所有的上级都没有找到此类;

    则在本级查找此类,找到:本类加载器调用findClass(name)方法(每个类加载器自己扩展的)来加载这个类。找不到:抛出类找不到异常。

  • 注意:

    • 这里的双亲委派,就是调用类加载器的loadclass方法时,查找类的规则
    • 这里的双亲指的是上级,他们并没有继承关系。

线程上下文类加载器

前提:在使用jdbc时,要加载Driver驱动(Class.forName("com.mysql.jdbc.Driver")),不写它时,此驱动也是会被正常加载的。

问题提出:DriverManager(java.sql.DriverManager)是启动类路径下的,故它的类加载器是Bookstrap ClassLoader,会到JAVA_HOME/jre/lib下搜索类,显然此路径下是没有mysql-connector-java-5.1.48.jar包的。

那DriverManager在静态代码块中怎样正确的加载com.mysql.jdbc.Driver呢?

加载方法:

打破了双亲委派的模式,使用应用程序类加载器启动类的加载

  1. 使用ServiceLoader机制加载驱动,即SPI ------> 使用应用程序类加载器启动类的加载,
  2. 使用jdbc.drivers定义的驱动名加载驱动 ------> 使用应用程序类加载器启动类的加载

体现了面向接口编程+解耦的思想

注:线程上下文类加载器是当前线程使用的类加载器,

在线程启动时,由jvm默认将应用程序类加载器赋值给当前线程。

自定义类加载器

  1. 需要自定义类加载器的情况?
    • 想加载非classpath随意路径中的文件
    • 都是通过接口来使用实现,希望解耦时常用在框架设计
    • 这些类希望予以隔离,不同应用的同名类都可以加载,不冲突,常见于tomcat容器
  2. 步骤:
    1. 继承ClassLoader类
    2. 要遵循双亲委派机制,重写findClass()方法
      • 注意:不是重写loadClass方法,否则不会走双亲委派机制
    3. 读取类文件的字节码
    4. 调用父类的defineClass方法来加载类
    5. 使用者调用该类加载器的loadClass方法

类加载器介绍

上一篇:matplotlib 并列条形图


下一篇:Arduino参考手册-函数和变量及电路图