六、类装载器

一、类装载流程

在这里插入图片描述

  • 加载

    • 类装载的第一个阶段;
    • 获取类的二进制流;
    • 将二进制流代表的存储结构转为方法区的运行时数据结构;
    • 在java堆中生成对应的java.lang.Class对象。
  • 链接 - 验证(确保二进制流中的信息符合java虚拟机规范)

    • 文件格式验证
      • 是否以0xCAFEBABE开头;
      • 版本号是否在虚拟机可接受的范围;
      • 常量池中是否有不被支持的常量类型;
      • 是否有只想不支持的 或 不存在的常量的索引;
    • 元数据验证
      • 是否有父类,除Object外都应该有父类;
      • 是否继承了不能被继承的类(final修饰的类);
      • 非抽象类是否实现了所有父类的抽象方法;
      • 子类是否覆盖了父类的final属性;
      • 子类是否出现了不符合规则的重载;
    • 字节码验证(过程复杂)
      • 运行时检查,确定语义是否合法;
      • 对方法体进行校验,保证运行时不会损害虚拟机;
      • 保证操作数栈的数据类型和指令代码正常配合;
      • 保证指令代码能跳转到正确的位置;
    • 符号引用验证
      • 检查符号引用描述的类是否存在;
      • 检查当前类是否有权限访问符号引用中的类、字段、方法。
  • 链接 - 准备

    • 为类中定义的静态变量(ststic修饰)分配内存并设置初始值;
    • public static int a=1 在准备阶段会为a分配内存,并将初始值设为0,在初始化是再将a设为1;
    • final static修饰的变量会直接设置为正确值;
    • 实例变量不会再准备阶段分配内存,只有再对象实例化时才会随对象一起分配再堆中。
  • 链接 - 解析

    • 将符号引用替换成直接引用。
  • 初始化

    • 初始化类构造器;
    • static变量赋值,static{}执行;
    • 子类初始化前,会先初始化父类;
    • 初始化是线程安全的。
  • 类装载器 - ClassLoader

    • ClassLoader是一个抽象类;
    • ClassLoader读入java字节码,将类装载到jvm中;
    • ClassLoader负责类装载过程中的加载阶段。
    • public Class<?> loadClass(String name) :载入并返回一个class;
    • protected final Class<?> defineClass(byte[] b, int off, int len):定义一个类;
    • protected Class<?> findClass(String name):查找class;
    • protected final Class<?> findLoadedClass(String name):查找已经加载的类。
  • 内置ClassLoader在这里插入图片描述

    • BootStrap ClassLoader:最顶层ClassLoader,C++实现,加载%JAVA_HOME%/lib/rt.jar,或-Xbootclasspath指定目录下的jar;
    • Extension ClassLoader:扩展ClassLoader,继承ClassLoader,加载%JRE_HOME%/lib/ext 目录下的jar包和类,或-Djava.ext.dirs指定目录的jar包;
    • App ClassLoader:应用程序ClassLoader,继承ClassLoader,负责加载classpath目录下的jar,或-Djava.class.path指定目录的jar包;
    • Custom ClassLoader:自定义ClassLoader,继承ClassLoader自定义的类加载器,加载自定义目录下的jar;
    • 双亲委派:加载器接受加载请求之后,会先检查该类是否已被自己加载,若没有加载会委派给父类装载器检查,依次检查完所有父类装载器,当存在父类装载器加载过请求类,则认为该类已被加载;若所有父类装载器都没有加载过该类,则从最顶层父类加载器开始加载该类;(CustomClassLoader —> BootstrapClassLoader);
      写两个HelloLoader类,一个打成jar包放在自定义目录下,另一个正常编译,配置jvm参数:-Xbootclasspath/a:C:\study\jvm\classLoader\jvm-project-1.0-SNAPSHOT.jar;
      在这里插入图片描述
      在这里插入图片描述
    public class HelloLoader {
        public void print(){
            System.out.println("I am in bootloader");
        }
    }
    
    public class HelloLoader {
        public void print(){
            System.out.println("I am in apploader");
        }
    }
    
    public class JVMTest extends ClassLoader{
    
        public static void main(String[] args) {
            HelloLoader helloLoader = new HelloLoader();
            helloLoader.print();
        }
    }
    
    执行上述程序,控制台打印并非编译的apploader,证明先加载了-Xbootclasspath/a:C:\study\jvm\classLoader\jvm-project-1.0-SNAPSHOT.jar中的HelloLoader。在这里插入图片描述
    • 双亲委派作用:防止类被重复加载,防止核心类被替换;
    • 双亲委派存在问题:顶层ClassLoader无法使用下层ClassLoader加载的类;
    • Thread. setContextClassLoader():上下文加载器,在顶层ClassLoader中传入底层ClassLoader实例,用以解决顶层ClassLoader访问不到底层Class Loader的问题;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值