Java类加载基本过程详细介绍
基本过程:
- 根据类的全限定名称加载定义类的二进制字节流。
- 将字节流代表的静态存储结构转化为方法区的运行时数据结构
- 内存中生成一个代表这个类的java.lang.Class对象,作为方法去这个类的各种数据访问入口
数组类本身不通过类加载器创建,由java虚拟机直接创建,数组类的元素类型由类加载器加载。
数组类的元素类型:数组去掉所有维度后的类型,
文件格式验证:
- 0xCAFEBABY 魔数开头;
- 主次版本号当前虚拟机可处理;
- 常量类型;
- 索引执行类型;
- utf8编码数据类型,
元数据验证:字节码描述信息语义分析:
- 是否有父类;
- 父类是否继承了final修饰的类;
- 非抽型类是否实现了父类或接口中需要实现的方法;
- 类中的字段、方法的覆盖,重载矛盾;
字节码验证:通过语义流及控制流分析确定程序予以的合法性,正确性,方法体分析验证。
- 符号引用验证:虚拟机将符号引用转化为直接引用时候,解析阶段,对类自身以外信息进行匹配性验证
- 符号引用中通过字符描述的全限定名是否能找到对应的类;
- 指定类中是否存在符合方法字段的描述符,及简单名称所描述的方法和字段;
- 符号引用中类,字段,方法的访问性。
准备:在方法区中为类变量分配内存及设置类变量初始值。
- 初始值通常为数据类型的零值,final修饰的值直接初始化为相应值。
- 类变量为static修饰的变量,区分于实例变量。
解析:虚拟机将常量池中的符号引用替换为直接引用过程
CONSTANT_Class_info,CONSTANT_Fieldref_info,CONSTANT_Methodref_info..
- 符号引用:以一组符号来描述所引用的目标,任何形式的字面量,只要使用时能无歧义的定位到目标,,与虚拟机内存实现无关,无关引用目标是否加载。
- 直接引用:直接指向目标的指针,偏移量或间接定位到目标的句柄,和虚拟机实现的内存相关,直接引用相关的目标对象必须已加载。
- 。。。
初始化:开始执行类定义中的Java程序代码。执行类构造器<cinit>()方法,
<cinit>():
- 编译器根据类文件中定义顺序自动收集类中的类变量的赋值动作和静态语句块儿的语句合并产生,静态语句块儿只能访问到其前定义的变量。
- 区别于类的构造方法,不需要显示的调用父类构造器,虚拟机保证子类的<cinit>()执行之前父类的<cinit>()已经执行完成。
- 父类中的静态语句块儿执行于前。
- <cinit>()对于类或接口不是必须的,如果没有变量赋值操作或静态语句块儿,则不生成。
- 接口的<cinit>()不需要先执行父接口的<cinit>(),同样接口的实现类<cinit>()也不需要。
- 线程安全:虚拟机保证多线程环境中<cinit>()正确的加锁,同步,同一时间只能有一个线程访问初始化类的<cinit>()
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!