Learn && Live
虚度年华浮萍于世,勤学善思至死不渝
Hey,欢迎阅读Connor学JVM系列,这个系列记录了我的JVM基础知识学习、复盘过程,欢迎各位大佬阅读斧正!原创不易,转载请注明出处:http://t.csdn.cn/YszaF,话不多说我们马上开始!
(1)Class文件是一组以字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑排列,中间没有任何分隔符
(2)Class文件结构采用一种类似于C语言结构体的伪结构,只有两种数据类型
magic
(1)魔数,u4
(2)它的唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件,值为0xCAFEBABE。
(3)此外如GIF等图片格式的文件头中也有魔数
(4)使用魔数而不是扩展名来进行识别主要是基于安全考虑,因为文件扩展名可以随意改动
minor_version
(1)次版本号,u2
(2)JDK1.2之前用于指定该JDK版本支持的Class文件版本号的下限,如JDK1.1支持版本不低于45.0
(3)JDK1.2至JDK12之前次版本号均为使用,固定为0
(4)JDK12次版本号用于标识“技术预览版”,如果Class文件中使用了该版本尚未列入正式特性的预览功能,则将次版本号指定为65535
major_version
(1)主版本号,u2,
(2)用于指定该JDK版本支持的Class文件版本号的上限,如JDK1.1支持版本不高于45.65535
(3)高版本的JDK能向下兼容以前版本的Class文件,但不能运行以后版本的Class文件,虚拟机会拒绝执行超过其版本号的Class文件
constants_pool_count
(1)常量池容量计数值,u2
(2)这个计数值从1而不是从0开始,这样做可以用0来表示不引用任何一个常量池项目的索引值
constrants_pool
(1)常量池,不定长,长度与池中常量的个数和长度有关
(2)主要存放两大类常量:字面量、符号引用。字面量包括文本字符串、final常量等,符号引用可以包含下面几类
(3)每一项常量都是一个表,表的结构根据类型的不同而各不相同
access_flags
(1)访问标志,u2
(2)用于识别一些类或接口层次的访问信息或识别是否为注解、枚举、模块,如:
this_class
(1)类索引,u2
(2)用于确定这个类的全限定类名
super_class
(1)父类索引,u2
(2)用于确定这个类的父类的全限定类名,除Object类外,所有Java类的父类索引只能为1
interfaces
(1)接口索引集合,不定长
(2)按implements(若这个Class文件表示一个接口,则为extends)后的接口顺序从左到右排列在接口索引集合中
fields_count
(1)接口或类中声明的变量的个数,u2
(2)包括成员变量(类变量 + 实例变量),不包含局部变量
fields
(1)字段集合,不定长
(2)用于描述类或接口中定义的成员变量的修饰符(权限、static、final、volatile、transient等)、类型、名称信息
(3)字段集合中不会列出从父类或父接口中继承来的字段,但有可能出现原本Java代码中不存在的字段,如在内部类中为了保持对外部类的访问性,编译器会自动添加指向外部类实例的字段
methods_count
方法的个数,u2
methods
(1)方法集合,不定长
(2)用于描述方法的修饰符(权限、static、final、synchronized、native、abstract)、返回值类型、名称、参数(数量、类型及顺序)
(3)方法内的代码在经过Javac编译器编译成字节码指令后,存放在Code属性中,而不是方法集合中
(4)重载:若两个方法有相同的名称和特征签名,但返回值不同,是可以合法存在于同一个Class文件的。特征签名是指一个方法中各个参数在常量池中的字段符号引用的集合,注意这里不包含返回值
attributes_count
属性个数,u2
attributes
属性表集合,Class文件、字段表、方法表都可以携带自己的属性表集合,属性表集合不要求各个属性表具有严格顺序,只要不重名即可
(1)Code,方法表的属性集合中,Java程序方法体内的代码经Javac编译器处理变为字节码指令存储在其中,可以包含以下属性
(2)Exceptions,方法表中与Code属性平级的属性,作用是列举出方法throws关键字后列举的异常
(3)LineNumberTable,Code属性中
(4)LocalVariableTable,类中
(5)LocalVariableTypeTable,类中,JDK5新增属性,使用特征签名(Signature)描述泛型参数化类型
(6)ConstantValue,用于通知虚拟机自动为静态变量赋值
(7)InnerClasses,用于记录内部类和外部类之间的关联。如果一个类定义了内部类,编译器会自动为它和它的内部类生成该属性
(8)Signature,用于单独记录泛型签名信息,因为字节码中所有泛型信息编译在编译之后都会被擦除掉
(9)MethodParameters,方法表中不定长属性,用于记录方法的各个形参名称和信息