【JVM-7】类的几个加载阶段

一、加载

java类变成字节码以后,要运行的话需要类加载器,将将类的字节码载入方法区中,内部采用C++的instanceKlass描述java类(底层)。

java无法直接访问instanceKlass,所以中间需要一系列的转换。内部重要的field(域)有:

  • _java_mirror 即 java 的类镜像,例如对 String 来说,就是 String.class(这就是instanceKlass的镜像),作用是把 klass 暴露给 java 使用—桥梁作用
  • _super 即父类
  • _fields 即成员变量
  • _methods 即方法
  • _constants 即常量池
  • _class_loader 即类加载器
  • _vtable 虚方法表 (构造方法入口地址…)
  • _itable 接口方法表
    在这里插入图片描述

注意点:

  • 如果这个类还有父类没有加载,先加载父类
  • 加载和链接可能是交替运行的
  • instanceKlass 这样的【元数据】是存储在方法区(1.8 后的元空间内),加载的同时会在java堆内存中生成_java_mirror的镜像

二、链接

  1. 验证。 验证类是否符合JVM规范,安全性检查
  2. 准备。为 static 变量分配空间,设置默认值

总结:static变量分配空间和赋值阶段——准备阶段?初始化阶段?
注意点:static变量分配空间和赋值是两个步骤,分配空间在准备阶段完成,赋值在初始化阶段完成。如果static变量是final的基本类型,以及字符串常量,那么编译阶段值就确定了,赋值在准备阶段完成。如果static变量是final的,但属于引用类型,那么赋值也会在初始化阶段完成。

  1. 解析。将常量池中的符号引用解析为直接引用
    符号引用仅仅只是符号 直接引用后确切知道类在内存中的位置 (字段和方法的内存地址)

三、初始化

该part要想明白的问题: 这个类中的元素到底要不要初始化??

类的初始化时懒惰的(用的时候才初始化)
初始化的定义:执行了<cinit>方法,也就是执行静态方法,给静态变量赋值
在这里插入图片描述
classLoader只会导致类的加载,解析和初始化都不做

四、总结

加载-> 验证-> 准备 ->解析-> 初始化

  1. 加载 :类加载器查找字节流,创建类的过程
  2. 验证: 被加载的类要满足jvm的加载条件
  3. 准备: 为被加载的静态字段分配内存
    构造跟类层次相关的数据结构,比如方法表
  4. 解析 符号引用到实际引用
  5. 初始化 <cinit>

被final修饰的静态字段,并且数据类型是基本的数据类型或者字符串,会被标记位常量。其余的静态字段和静态代码块会被java编译器一同放进<clinit>方法中(类构造器)。 --实例构造器为<init>
在初始化阶段,会为常量值字段赋值,并执行<clinit>方法。多个线程同时初始化一个类,会通过加锁的方式来确保<clinit>方法只会被执行一次

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值