Java 虚拟机类加载机制


类加载的过程

1.加载

  • 通过一个类的全限定名来获取定义此类的二进制字节流

  • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构

  • 在内存中生成一个代表这个类的java.lang.Class 对象,作为方法区这个类的各种数据的访问入口

2.验证

验证共有,文件格式验证,元数据验证,字节码验证,符号引用验证

文件格式验证

  • 是否以魔数0xCAFEBABE开头
  • 主,次版本号是否在当前虚拟机处理范围之内
  • 常量池中的常量是否有不被支持的常量类型(检查常量tag标志)
  • 指向常量的各种索引值是否有指向不存在的常量或不符合类型的常量
  • CONSTANT_Utf8_info型的常量中是否有不符合UTF8编码的数据
  • Class 文件中各个部分及文件本身是否有被删除或附加的其他信息

元数据验证

  • 这个类是否有父类(除了java.lang.Object之外,所有的类都应当有父类)
  • 这个类的父类是否继承了不允许被继承的类(被fianl修饰的类)
  • 如果这个类不是抽象类,是否实现其父类或接口之中的要求实现的所有方法
  • 类中的字段,方法是否与父类产生矛盾(例如覆盖了父类的final字段,或者出现不符合规则的方法重载,例如方法参数都一致,但返回值类型却不同等)

字节码验证

  • 保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作,例如不会出现类似的这样的情况,在操作栈放置了一个int类型的数据,使用时却按long类型来加载本地变量中
  • 保证跳转指令不会跳转到方法体以外的字节码指令上
  • 保证方法体中的类型转换是有效的,例如可以把一个子类型对象赋值给父类数据类型,这是安全的,但是把父类对象赋值给子类数据类型,甚至把对象赋值给与它毫无继承关系,完全不相干的一个数据类型,则是危险和不合法的。

符号引用验证

  • 符号引用中通过字符串描述的全限定名是否能找到对应的类
  • 在指定类中是否在符合方法的字段描述符以及简单名称所描述的方法和字段
  • 符号引用中的类,字段,方法的访问行(private,protected,public,default)是否可被当前类访问。

3.准备

4.解析

解析动主要针对类或接口,字段,类方法,接口方法,方法类型,方法句柄和调用点限定符7类符号引用进行,分别对应于常量池
CONSTANT_Class_info,CONSTANT_Fieldref_info,CONSTANT_Methodref_info,
CONSTANT_InterfaceMethodref_info,CONSTANT_MethodType_info,CONSTANT_MethodHandle_info,
CONSTANT_InvokeDynamic_info
7种常量类型。

  • 类或接口的解析

  • 字段解析

  • 类方法解析

  • 接口方法解析

5.初始化


文章作者: coderpwh
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 coderpwh !
  目录