jvm:类加载器

类加载器

  • 加载器列表:

    加载哪的类 说明
    Bootstrap ClassLoader java_home/jre/lib 无法直接访问
    Extension ClassLoader java_home/jre/lib/ext 上级为Bootstrap,显示为null
    Application ClassLoader classpath 上级为Extension
    自定义类加载器 自定以 上级为Application
    • 存在一个层级关系:会优先询问上级是否已经加载;
  • 启动类加载器,Bootstrap ClassLoader:

  • 扩展类加载器,Exception ClassLoader:

  • 双亲委派:指调用类加载器的loaderClass方法时,查找类的规则;

    • 双亲,更应该翻译为上级更为合适,因为它并没有继承关系,

      1. 检查该类是否已经被本加载器加载;

      2. 如果没有被加载,判断是否有上级:

        1. 有上级,在递归调用上级的loadClass();
        2. 如果没有上级,则由Bootstrap ClassLoader加载;
      3. 到自己类加载里面,加载,否则报错;

        通过报错跳出递归,进入下级寻找;

    • 双亲委派类加载器:

      • mysql的DriverManager是由启动类加载器,加载,其中指明了加载驱动Driver方法;
      • 但是驱动Driver不在启动加载路径下,所以在Driver加载中,明确使用了应用加载器【Application ClassLoader】;
  • 线程上下文类加载【ContextClassLoader】:

    • ContextClassLoader:是当前线程使用的类加载,默认是应用程序类加载器,
    • 在每个线程启动的时候,jvm默认把应用程序加载器赋值给当前线程;
  • 自定义类加载器:

    • 什么时候需要自定义加载器:
      1. 想要加载非classpath随意路径中的类文件;
      2. 面向接口编程,希望解耦,常用在框架设计;
      3. 希望隔离不同版本,不同应用的同类型都可以被加载,不冲突,常见于tomcat容器;
    • 实现步骤:
      1. 继承ClassLoader父类;
      2. 遵从双亲委派机制,需要重写findClass方法;
      3. 读取类文件的字节码;
      4. 调用父类的defineClass方法来加载类;
      5. 使用该类加载器的loadClass方法;
    • 确定类相同:包名+类名+类加载器【对象】,三者相同;
      • 因此通过内加载器不是同一个对象,判定不是相同类,从而实现了隔离;
      • 通常情况下,启动类加载器,扩展应用加载器和应用类加载器都是单例实例化;
posted @ 2025-03-19 20:36  烟雨断桥  阅读(10)  评论(0)    收藏  举报