JVM类加载--初始化阶段赋值与准备阶段赋值对比

JVM类生命周期:

  1. 加载阶段:由ClassLoader来完成,ClassLoader将字节码以流的形式加载进内存,在元空间(方法区)生成类模板,并且在堆中生成其Class对象,做为访问元空间中类模板信息的接口。ClassLoader在整个类的加载过程(加载阶段,链接阶段,初始化阶段),只能影响到类的加载,无法通过Classloader去改变链接和初始化阶段。
  2. 链接阶段:1->验证(与加载阶段同时进行),验证字节码格式是否正确,语法分析等,2->准备,静态变量默认初始化,静态常量显式初始化(仅仅针对使用字面量的初始化),3->解析(在初始化阶段之后执行),符号引用转为直接引用,因为此时所有需要的类已经被加载到内存,有了具体的地址,这时就可以把符号引用变成直接引用。
  3. 初始化阶段,静态变量初始化(类中的字段),编译器生成clinit()方法,并且在初始化阶段执行(开始执行字节码指令了)。
  4. 用户使用上述加载的类,写具体的业务代码
  5. 类的卸载

本文研究类加载过程中的初始化阶段,主要就是类静态变量的显式赋值。

分为两种情况:

1.链接->准备 阶段的显式赋值

满足的条件:

  • 静态常量 static final
  • 字面量 进行显示赋值,字面量(保存在常量池中) 可以认为是有确定值的基本数据类型,还有具有确定值的string.

2.初始化阶段 的显式赋值

不满足1条件的 静态变量或者静态常量(非字面量) 显式赋值,都要在初始化阶段的clinit()方法中进行显式赋值

当然了,如果没有静态变量显式赋值,或者静态常量显式赋值(非字面量) ,则编译器不会生成clinit()方法。

 

再举例说明:

public static final String s1 = new String("helloWorld1");
public static final int NUM1 = new Random().nextInt(10);

上面的两个静态常量显式赋值,是在初始化阶段进行的,因为不是用字面量进行赋值的,还有另外一种理解,因为需要new对象,即执行代码,而最开始执行代码的地方,就是初始化阶段的clinit()方法,所以可以认为上面的显示赋值是在初始化阶段进行的。

Note:

  • 非静态方法的局部变量表的角标0,存放的是this指针,指向当前对象。
  • 静态方法的局部变量表的角标0,不存放this指针,因为静态方法是类级别的。

 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值