类加载过程:加载、连接、初始化

类的主要加载过程分为:加载Loading、连接Linking(验证、准备、解析)、初始化Initialzation。

加载Loading:
    这个加载指的是类加载过程中的一个环节,在加载阶段Java虚拟机需要完成三件事:

  • 通过一个类的全限定名获取定义此类的二进制字节流;、
  • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
  • 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

连接Linking:
    连接中又可分为:验证、准备、解析三个阶段。

  1. 验证Verify:
        主要是验证class文件的字节流是否符合当前虚拟机的要求(如开头是否是CAFEBABE),用于保证被加载类的正确性。
        主要包括四种验证:文件格式验证、元数据验证、字节码验证、符号引用验证。此处不做过多解释。

  2. 准备Prepare:
        用于给类变量(static修饰的)分配内存,并且给类变量设置默认初始值(这里是默认值,如:static int i = 1,这里给i赋的默认值是0,不是1)。

    :这里不包含final static修饰的静态常量。因为final在编译的时候就会分配,准备阶段就会显示初始化。也不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中。

  3. 解析Resolve:
        该阶段是将常量池的符号引用转换为直接引用的过程。解析主要针对类或接口、字段、类方法、方法类型等。

    注:这里的常量池对应字节码文件中的常量池
    在这里插入图片描述

初始化Initialzation:
    初始化阶段就是执行<clinit>(类构造器方法)的过程。此方法是javac编译器自动收集类中的静态变量的赋值动作和静态代码块中的语句合并而来,不需要自己定义,也不能和构造方法混淆,任何一个类都有构造函数,但如果一个类没有类变量和静态语句块,就不会生成<clint>方法。若该类具有父类,JVM会保证子类的<clinit>()执行前,父类的<clinit>()已经执行完毕。此外Java虚拟机必须保证一个类的<clinit>()方法在多线程环境中被同步加锁。
在这里插入图片描述
由于编译器收集的顺序是由语句在源文件出现的顺序决定的,所以也解释了以下问题:

public class Test1 {

    static {
        a = 2;
        // System.out.println(a);
    }

    public static int a = 1;

    public static void main(String[] args) {
        System.out.println(a);
    }
}

说明:结果a等于1,因为a在准备阶段,给了默认值为0,在初始化阶段编译器阶段收集的顺序又由语句在源文件的顺序决定,所以在静态代码块了给a显示赋值为2,在给a赋值为1,最终a为1(大家也可以通过javap -v反编译进行查看,a = 2,会比 a =1先执行。:这里如果去掉注释那一行,将会编译报错,提示“非法向前引用”。原因也是因为静态语句块只能访问到定义在静态语句块之前的变量,定义在它之后的变量,可以进行赋值,但不能访问。
在这里插入图片描述

以上就是类的加载过程,当类加载完就可以使用Using,使用完就是卸载Unloading。

谢谢观看。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值