JAVA——Class装载

概述:

JAVA Class文件的装载流程包含三个阶段:加载、链接、初始化。而链接又分为:验证、准备、解析三个步骤。
类并不是在任何时刻就马上装载的,他是需要一定的条件。正常情况下,类的装载分为主动和被动两种情况。其中主动装载会初始化一个类(这里所谓的初始化是初始化静态块和静态变量,而不是我们通常说的构造函数)。主动装载分为以下几种情况:

  1. 使用new关键字或者通过反射、克隆、反序列化来创建一个类的实例
  2. 调用类的静态方法
  3. 使用类或接口的静态字段时(不包括final)。
  4. 使用java.lang.reflect包中的反射类的时候
  5. 初始化子类的时候,要求先初始化父类
  6. 作为虚拟机,包含有main方法的那个类

以上几种情况,是我们的主动加载,主动不仅会加载一个类,还会连接初始化一个类。除主动加载类的方法外,其他的都是被动加载。如:通过一个子类调用父类的静态变量,我们只会初始化父类(即实际拥有静态变量的那个类,通过一个类引用静态常量(static final),实际上这种情况不仅不会初始化类,而且还不会加载这个类,这是因为我们的JAVA虚拟机在这种情况下,直接将常量放到了常量池中。


加载类

加载类分为三个阶段:
1. 通过类全名获取二进制数据流
2. 解析类的二进制数据流为方法区的数据结构
3. 创建java.lang.class类的实例,表示该类型
通常情况下,在加载一个类的时候,我们还会把他的父类加载到系统里面去。


链接:

链接分为三个步骤:

  1. 验证:他的目的是保证加载的字节码是合法、合理并合规的。这个过程主要做以下的事情:
    • 格式检查:判断类的二进制数据是否符合格式规范和要求,如是否以魔数数字开头,版本号是否被JVM支持,数据项是否拥有合法的长度等。
    • 语意检查:检查类的父类是否存在,是否存在继承final类等。
    • 字节码验证:对字节码进行验证,主要做判断字节码是否可以被正确执行,执行的指令是否存在或者正确
    • 引用符号验证:将符号引用进行验证,主要用来判断Class文件在其常量池会通过字符串记录自己将要使用的方法或者类,验证阶段就是用来检查这些方法或者类是否存在的,并且是否拥有权限访问,如果一个类找不到就会抛出NoClassDefFoundError,方法找不到就会抛出NoSuchMethodError。
  2. 准备:验证通过后,就会进入准备阶段,准备阶段会为这个类分配相应的内存空间,并设置初始值(常量值会被赋上正确的值,非常量值就直接默认初始化值,具体可以看书333页)。在准备阶段前,不会有任何JVM代码被执行。
  3. 解析:解析的工作就是将类、接口、字段、方法的符号引用转化为直接引用。也就是把一个类、接口、字段由符号值跟具体的内存地址偏移量相对应(比如说我们要调用methodA,在解析前我们只会记录一个字符串值,而解析后就直接将其实际方法调用的内存地址偏移量映射过来)。在这个过程中,会将字符常量(也就是直接string a=”abc”,这个abc就是字符常量)对应到字符常量拘留表中(这个拘留表会保存所有的字符常量值,并且相同的字符常量都会有同一个地址,通过intern()可以拿到地址值)。

初始化

类加载、验证完成后,就会执行类的初始化,类在加载验证后,会生成一个方法,这个clinit方法实际上是静态变量和静态块的初始化指令,在初始化的时候,会执行这个clinit方法,如果没有静态块或者静态变量,则这个方法为空。
值得注意的是,父类的clinit方法总是在子类的前面执行。并且clinit方法的执行是线程安全的,JVM会保证每次只执行一个类的初始化,所以我们一定要避免死锁问题:

public class StaticA{
    static try{
        Class.forName("StaticB");
    }
}

public class StaticB{
    static try{
        Class.forName("StaticA");
    }
}
上述代码就会出现死锁问题
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值