类加载机制

简单的来说,就是虚拟机把 class 文件加载到内存中,放在方法区,并且进行加载,链接,初始化的过程,其中链接又有验证,准备,解析的三个过程。最终变成虚拟机能使用的 java 类。

加载

也就是文件到内存的过程,把文件转化未字节流,并且依此来创建类。其中类加载过程中,需要类加载器来完成。

类加载器分为三种

  • 启动类加载器(BootStrap ClassLoader)
    • 常用来加载最为基础的类(lib 目录下的 jar 包中的类)
  • 扩展类加载器(ExtClassLoader)
    • 常用来加载次要、通用的类(lib/ext 目录下的 jar包)
  • 应用类加载器(AppClassLoader)
    • 加载应用程序路径下的类,加载 classpath 指定目录下的类。
  • 自定义类加载器(CustomClassLoader)
    • 自定义类加载器

这里的关系是,启动类加载器是共同的祖师爷,而且启动类加载器是没有自己的对象实例的。而其他的类加载器在此基础下,都是 java.lang.ClassLoader 的子类。

扩展类加载器的父类是启动类加载器,应用类加载器的父类是扩展类加载器。

那么者几个类的加载顺序如何?这里要提到双亲委派模式

双亲委派模式

一个类加载器在接受到请求之后,会将请求转发给自己的父类加载器,如果自己的父类加载器发现没要找到所请求的类的情况下,子类加载器才会尝试加载。(这里的父类会一层一层向上委托,直到顶层,在顶层不行的情况下,交给下来的一层一层子类看是否能加载)

好处

这样能防止类被重复加载,并且防止 Java 的 核心 API 被篡改,毕竟能自定义类加载器。

链接

将创建成的类合并到 Java 虚拟机,使之能够执行,供虚拟机使用。

其中分为三个过程。

  • 验证
  • 准备
  • 解析

验证

确保被加载的类符合 Java 虚拟机的约束条件。不会危害虚拟机的本身安全。其中包括

  • 文件格式校验
  • 元数据校验
  • 字节码校验
  • 符号引用校验

准备

对变量进行内存分配,注意这里针对的是 static 修饰的静态变量,对于 final 修饰的变量,在编译期间,就已经分配了内存。

  • 为被加载类的静态字段分配内存
  • 为静态字段设置初始值,注意这里初始值是 0 或 null,不是自己赋值的值
  • 构造其他根类层次结构的数据结构
    • 比如说实现虚方法的动态绑定的方法表

解析

将符号引用解析为实际引用。

那么符号引用是什么呢?

在类加载到 java 虚拟机之前,它是不知道它调用的其他类的方法,字段的具体地址为多少,甚至不知道自己的方法、字段,所用需要有一个引用暂时代替这一部分的具体地址。Java 虚拟机将会生成符号引号,在运行过程能够无歧义的定义未知。

举例来说,对于一个方法调用,编译器会生成一个包含目标方法所在类的名字、目标方法的名字、接收参数类型以及返回值类型的符号引用,来指代所要调用的方法。

  • 符号引用执行一个未被加载的类,或者未被加载的方法或字段。解析将会触发该类的加载。
  • 注意
    • JVM 规范中,并没有规定在链接阶段就得完成解析的过程。它是这样规定的
      • 如果某些字节码使用了符号引用,那么在执行这些字节码之前,需要完成对这些符号引用的解析。

初始化

为标记为常量值的字段赋值,以及执行 方法的过程,该过程有加锁。

也就是执行静态代码块和为静态变量赋值。这是类加载阶段的最后过程。

注意

  • 直接赋值的静态字段被 final 所修饰,它的类型又是基本类型或字符串时。
    • 标记成常量值
    • 初始化直接由 JVM 完成
  • 什么是
    • 除了直接赋值的操作,以及所有静态代码块的代码,则会被 Java 编译器置为同一方法中。并且命名为

只有完成初始化,类才是可执行的状态。并且只用在对类的主动使用的时候,才会触发初始化。

那么如何触发初始化?

  • 虚拟机启动,初始化用户指定
  • new 指定的类
  • 调用静态方法,初始化静态方法的类
  • 访问静态字段,初始化静态字段的类
  • 子类初始化触发父类初始化
  • 接口定义了一个 default 方法,如果直接或间接实现的类初始化,触发接口初始化。
  • 使用反射 API 对某个类反射调用,初始化该类
  • 初次调用 MethodHandle 实例时,初始化该 MethodHandle 指向方法所在的类。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值