类加载内存与反射
Class类文件的结构
Class文件是一组以8字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑排列在class文件中,中间没有任何分隔符,这使得class文件中存储的内容几乎是全部程序运行的程序。
通过16进制查看器查看.class文件:
打开后的结果为:
Java虚拟机规范规定,Class文件格式采用类似C语言结构体的伪结构来存储数据,这种结构只有两种数据类型:无符号数和表。
无符号数属于基本数据类型,主要可以用来描述数字、索引符号、数量值或者按照UTF-8编码构成的字符串值,大小使用u1、u2、u4、u8分别表示1字节、2字节、4字节和8字节。
表是由多个无符号数或者其他表作为数据项构成的复合数据类型,所有的表都习惯以“_info”结尾。那么表是干嘛的呢?表主要用于描述有层次关系的复合结构的数据,比如方法、字段。需要注意的是class文件是没有分隔符的,所以每个的二进制数据类型都是严格定义的。
在class文件中,主要分为魔数、Class文件版本号、常量池、访问标志、类索引(还包括父类索引和接口索引集合)、字段表集合、方法表集合、构造器表集合等。
大概可分成几类:
1、结构信息。包括class文件版本号,魔数,类索引(还包括父类索引和接口索引集合)
2、元数据。对应于Java源码中声明与常量的信息。常量池,字段表集合,方法表集合,构造器表集合等。
3、方法信息。对应Java源码中语句和表达式对应的信息。包含字节码、异常处理器表、求值栈与局部变量区大小、求值栈的类型记录、调试符号信息等。
总之,Class对象包含了一个类中我们需要的所有信息。
从java文件到Class对象
类的加载过程
类加载过程解释:
-
加载
将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象。 -
链接:将java类的二进制代码合并到JVM的运行状态之后的过程。
链接又分成三个过程:- 验证:确保加载的类信息符合JVM规范,没有安全方面的问题。
- 准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。
- 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。
-
初始化:
- 执行类构造器< clinit>()方法的过程。类构造器< clinit>()方法是由编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造改类对象的构造器)。
- 当初始化一个类的时候,如果发现其父类害没有初始化,则需要先触发其父类的初始化。
- 虚拟机会保证一个类的< clinit>()方法在多线程环境中被正确加锁和同步。
通过类加载过程可以清晰的看到Class对象的生成与其类属性的初始化过程。
网友评论