ClassLoader工作机制

1,ClassLoader:ClassLoader的加载机制和加载类的过程

  • ClassLoader除了能将 Class 加载到JVM中之外,还有一个重要的作用就是审查每个类应该由谁加载,它是一种父优先的等级加载机制,还有一个任务就是将Class 字节码重新解析成 JVM 统一要求的对象格式。

  • 如果只想在运行时能够加载自己指定的一个类,可以用 this.getClass().getClassLoader().loadClass(“class”),调用 ClassLoader 的 loadClass 方法获取这个类的 Class 对象,这个 loadClass 方法还有重载方法,你同样可以决定在什么时候解析这个类。

  • ClassLoader是一个抽象类,它还有很多子类,我们如果要实现自己的 ClassLoader , 一般都会继承 URLClassLoader 这个子类,因为这个类实现了大部分的工作。

2,ClassLoader 的等级加载机制:三层 ClassLoader

  • Bootstrap ClassLoader: 这个 ClassLoader 主要加载 JVM 自身工作需要的类,完全由 JVM 自己控制,它仅仅是一个类的加载工具而已,没有父加载器,也没有子加载器。

  • ExtClassLoader: 扩展类加载器

  • AppClassLoader: 它的父类是 ExtClassLoader ,这个目录就是我们经常 使用到的 classpath。

    • 如果我们要实现自己的类加载器,不管是继承加载类 ClassLoader , 还是继承 URLClassLoader 类,或者其他子类,父加载器都是 AppClassLoader,因为不管调用哪个父类构造器,创建的对象都必须最终调用 getSystemClassLoader() 作为父加载器,而调用 getSystemClassLoader() 获取到的正是 AppClassLoader。
  • JVM 加载 class 文件的两种方式:

    • 隐式加载: 不通过在代码里调用 ClassLoader 来加载需要的类,而是通过 JVM 来自动加载需要的类到内存的方式。如: 当我们在类中继承或者引用某个类时, JVM 在解析当前这个类时发现引用的类不在内存中,那么就会自动将这些类加载到内存中。

    • 显式加载:在代码中通过调用 ClassLoader 类来加载一个类的方式,如: 调用 this.getClass().getClassLoader().loadClass() 或者 Class.forName(),或者我们自己实现的 ClassLoader 的findClass() 方法等。

  • 加载、验证、准备、解析、初始化

    • 加载字节码到内存
    • 字节码验证,以确保格式正确,行为正确。
    • 类准备:准备代表 每个类中定义的字段、方法、实现接口所必须的数据结构
    • 解析,类装入器装入类所引用的其他所有类。
    • 初始化Class对象:在类中包含的静态初始化器都被执行,在这一阶段末尾静态字段被初始化为默认值。
  • 常见加载类错误

    • ClassNotFoundException

      • 这个异常通常发生在显式加载类的时候,
      • 显式加载一个类通常由如下方式:
        • 通过类 Class 中的 forName()方法
        • 通过类 ClassLoader 中的 loadClass()方法
        • 通过类 ClassLoader 中的 findSystemClass() 方法
      • 出现这类错误,就是当 JVM 要加载指定文件的字节码到内存时,并没有找到这个文件对应的字节码,即这个文件并不存在。解决的办法:检查在当前 classpath 目录下有没有指定的文件存在,通过如下命令获取当前的 classpath 路径: this.getClass().getClassLoader().getResource(“”).toString()
    • NoClassDefFoundError

      • 因为在命令行中没有加类的包名
    • unsatisfiedLinkError

      • 可能是将 JVM 中的某个 lib 删除了。
    • ClassCastException

      • 强制类型转换时出现这个错误:先通过 instanceof 检查是不是目标类型,然后再进行强制类型转换。

3,实现自己的 ClassLoader

  • 一种方式是 extends ClassLoader
  • 另一种常见的方式是继承URLClassLoader类:将制定的目录转化成 URL 路径,然后作为参数创建 URLPathClassLoader 对象,那么这个 ClassLoader 在加载时就在 URL 指定的目录下查找指定的类文件。

你可能感兴趣的:(Java-Web)