无关性的基石
java虚拟机不与包括java语言在内的任何一门语言绑定,只与.class文件这种特定的二进制文件相关联
Class文件的结构
魔数与Class文件的结构
class文件是一组以八个字节为单位的二进制流,u1,u2,u4,u8分别代表了1个字节,2个字节.......
class文件不像XML那些描述性的语言,它没有任何的分隔符,对于文件里的内容,无论是里面元素的顺序还是数量都是被严格规定好的,全都不允许改变
魔数与Class文件
class文件的前4个字节(class文件的显示一般是用的十六进制,一个十六进制数表示半个字节)被称为魔数,它唯一的作用是确定这个文件是不是被java虚拟机可以接受的class文件,其中第5、6个字节标明了次版本号,7、8个字节标明了主版本号
常量池
紧接着的两个字节便是标明了常量池中常量的数量这个计数是从1开始的,例如这个002f(47)就是常量池的数量,正确的常量数为47-1也就是46个(通过javap -v *.class访问class的可读性文件 )
常量池数量之后便是常量池内元素的相关信息和长度,常量池主要存放两大类常量:字面量和符号引用
字面量主要包含一些文本信息和被final修饰的常量等,
而符号引用则主要包含下面几类常量:
- 被模块化导出或者开放的包(Package)
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
- 方法句柄和方法类型
- 动态调用点和动态常量
查表时首先通过第一个字节判断类的类型,接着再查该类的类型的表,得到该类的相关信息
访问标志
再常量池访问结束后,紧接着的2个字节就代表了访问标志,这个标志用来标明类的一些信息,比如这个类是类还是接口,是否被final修饰等信息,见下表(0x表示是十六进制的数)
例如这个0021就是该class文件的访问标志即为0x0001|0x0020,所以该class文件的访问标志为ACCPUBLIC和ACC_SUPER
通过javap - v *.class验证
类索引、父类索引与接口索引集合
类索引和父类索引都是一个u2类型的数据,而接口索引是一个u2类型数据的集合,类索引用于确定这个类的全限定名,父类索引用于确定父类的全限定名
0x000b是类索引、0x00c是父类索引,0x000b对应着常量池#11号常量(注意如果该类没有打包也就是使用package,那么全限定名就是类名本身)
0x00c是父类索引,对应着常量池#12号常量
字段表集合(fields)
字段表结构
字段修饰符放在access_flags中,对照如下,000a(10)表示标识符为ACC_PRIVATE+ACC_STATIC
注意ACC_FINAL标志值时0x0010十六进制,0x0010表示的时16而不是10
方法表集合
访问标志access_flags,名称索引name _index、描述符索引descriptor_index