Class类文件的结构
-
魔数与Class文件的版本。
-
常量池:Class文件里的资源仓库。
- 字面量:如文本字符串,被声明为final的常量。
- 符号引用
- 被模块导出或者开放的包(Package)
- 类和接口的全限定名(Fully Qualified Name)
- 字段的名称和描述符(Descriptor)
- 方法的名称和描述符
- 方法句柄和方法类型(Method Handle、Method Type、Invoke Dynamic)
- 动态调用点和动态常量(Dynamically-Computed Call Site、Dynamically-Computed Constant)
- Java代码在进行Javac编译的时候,并不像C和C++那样有“连接”这一步骤,而是在虚拟机加载Class文件的时候进行动态连接。
-
访问标志:用于识别一些类或者接口层次的访问信息。包括:这个Class是类还是接口;是否定义为public类型;是否定义为abstract
类型;如果是类的话,是否被声明为final;等。
-
类索引、父类索引与接口索引集合:用来确定该类型的继承关系。
-
字段表集合:用于描述接口或者类中声明的变量。
-
方法表集合:括访问标志(access_flags)、名称索引(name_index)、描述符索引(descriptor_index)、属性表集合(attributes)。
-
属性表集合:
-
Code:Java程序方法体里面的代码经过Javac编译器处理之后,最终变为字节码指令存储在Code属性内。接口或者抽
象类中的方法就不存在Code属性。
-
Exceptions:是列举出方法中可能抛出的受查异常。
-
LineNumberTable:描述Java源码行号与字节码行号(字节码的偏移量)之间的对应关系。如果选择不生成LineNumberTable属性,对程序运行产生的最主要影响就是当抛出异常时,堆栈中将不会显示出错的行号,并且在调试程序的时候,也无法按照源码行来设置断点。
-
LocalVariableTable:描述栈帧中局部变量表的变量与Java源码中定义的变量之间的关系。如果没有生成这项属性,最大的影响就是当其他人引用这个方法时,所有的参数名称都将会丢失。
-
LocalVariableTypeTable:由于描述符中泛型的参数化类型被擦除掉,描述符就不能准确描述泛型类型了,LocalVariableTypeTable使用字段的特征签名来完成泛型的描述。
-
SourceFile:记录生成这个Class文件的源码文件名称。
-
SourceDebugExtension:存储额外的代码调试信息。
-
ConstantValue:通知虚拟机自动为静态变量赋值。
- 对非static类型的变量(也就是实例变量)的赋值是在实例构造器()方法中进行的;
- 如果同时使用final和static来修饰一个变量,并且这个变量的数据类型是基本类型或者java.lang.String的话,就将会生成ConstantValue属性来进行初始化。
- 如果这个变量没有被final修饰,或者并非基本类型及字符串,则将会选择在()方法中进行初始化。
-
InnerClasses:记录内部类与宿主类之间的关联。
-
Deprecated:属性用于表示某个类、字段或者方法,已经被程序作者定为不再推荐使用,它可以通过代码中使用“@deprecated”注解进行设置。
-
Synthetic:代表此字段或者方法并不是由Java源码直接产生的,而是由编译器自行添加的。
-
StackMapTable:这个属性会在虚拟机类加载的字节码验证阶段被新类型检查验证器(TypeChecker)使用,目的在于代替以前比较消耗性能的基于数据流分析的类型推导验证器。
-
Signature:它是一个可选的定长属性,可以出现于类、字段表和方法表结构的属性表中。记录泛型签名信息。弥补了反射无法获得泛型(泛型擦除)。
-
BootstrapMethods:用于保存invokedynamic指令引用的引导方法限定符。
-
MethodParameters:记录方法的各个形参名称和信息。
-
模块化相关属性:JDK 9的一个重量级功能是Java的模块化功能。
-
运行时注解相关属性:使用反射API来获取类、字段或方法上的注解时,返回值就是通过这个属性来取到的。
-