access建立两个字段唯一索引_Java .class文件 访问标志,索引,字段表,方法表

访问标志

在常量池结束之后紧接着的两个字符代表访问标志,这个标志用于识别一些类或者接口的访问信息,比如是个类还是一个接口,是否是public等

两个字节一共有16个标志位可以使用,目前只定义了9个,没有标志位的时候要按照0处理,按照上一接的内容进行查找可以发现访问标志是0x0021,能够读出来是0x0001 | 0x0020,所以他对应的是public + class,和我们的代码相吻合

类索引、父类索引、接口索引集合

类索引和父类索引都是u2类型的数据,接口索引集合是一组u2类型的集合,class文件通过这三项来确定该类型的继承关系。

类索引用来确定这个类的全限定名,父类索引用来确定这个类的父类的全限定名,注意到所有的类都至少有一个父类java.lang,Object,所以除了这个类以外所有的类的父类索引都不是0

接口索引用来描述这个类实现了哪些接口,这些接口按照implements关键字后的接口顺序从左到右排列在接口索引集合中。

类索引、父类索引和接口索引集合都按顺序排列在访问标志之后,类索引和父类索引用两个u2类型的索引值表示,它们各自指向一个类型为CONSTANT_Class_info的类描述符常量,通过CONSTANT_Class_info类型的常量中的索引值可以找到定义在CONSTANT_Utf8_info类型的常量中的全限定名字符串。

1d1a732a7c1649fd1e63ce82aa324aa0.png

还是同样的.class文件,我们可以读到访问标志后面的3个索引为3,4,0,其中0表示没有接口

192b3e0b1d3536e4a7ceebdd18ff64d5.png

然后我们可以找到对应的第3和第4个常量,两个class,这两个class又可以继续索引到第十七和第十八个常量,正好是我们的类和父类的名字

字段表集合

字段表用于描述接口或者类中声明的变量。Java语言中的字段包括类级变量以及实例级变量(类变量也叫静态变量,也就是在变量前加了static 的变量。实例变量也叫对象变量,即没加static 的变量),但是不包括在方法内部声明的变量。

对一个字段,它的描述符包括作用域,实例变量还是类变量,可变性(final),并发可见性(volatile),可否被序列化(transient)等等

上述这些信息中,各个修饰符都是布尔值,要么有某个修饰符,要么没有,很适合使用标志位来表示。而字段叫做什么名字、字段被定义为什么数据类型,这些都是无法固定的,只能引用常量池中的常量来描述。

d419c186f76a1e7af0638bc55eb0ea30.png
字段表结构

跟随access_flags标志的是name_index和descriptor_index,它们都是简单的对常量池的引用,代表它的名字和描述符。

“org/fenixsoft/clazz/TestClass”是这个类的全限定名,仅仅是把类全名中的“.”替换成了“/”而已,为了使连续的多个全限定名之间不产生混淆,在使用时最后一般会加入一个“;”号表示全限定名结束。简单名称则就是指没有类型和参数修饰的方法或者字段名称,这个类中的inc()方法和m字段的简单名称分别就是“inc”和“m”。

描述符的作用是用来描述字段的数据类型、方法的参数列表(包括数量、类型以及顺序)和返回值。根据描述符规则,基本数据类型以及代表无返回值的void类型都用一个大写字符来表示,而对象类型则用字符L加对象的全限定名来表示。

6359b4cf7fbb645c9db1a73c17ed8529.png
描述符标识字符含义

对于数组类型,java.lang.String[][]会被记录成[[Ljava/lang/String;int[]将会被记录成[I

用描述符来描述方法的时候,先参数列表后返回值,参数列表按照参数的顺序放在一组小括号()只中,比如方法int indexOf(char[]source,int sourceOffset,int sourceCount,char[]target,int targetOffset,int targetCount,int fromIndex)的描述符为([CII[CIII)I

9df8e84de66f8504011d74bc508f0566.png

这几个字节表示了

01 -> 1个字段
02 -> access_flags -> private
05 -> name_index -> 常量池第五个,m
06 -> descriptor_index -> 字符描述符 ,指向第六个常量,I,表示是int型

方法表集合

Class文件存储格式中方法的描述对字段的描述采用了几乎完全一致的方式,方法表的结构如同字段表一样。

fa772ff35a27267e3117521f174fae05.png

注意到一件事情,那就是到现在我们都没有提方法里面的代码去哪里了,实际上Javac编译,翻译成字节码指令之后,代码都被存访在方法属性表集合中一个名为code的属性里面。

e75d8f513f37052ac0ce5a884bbf159e.png

从我们的class文件中可以分析出两个方法,一个是<init>,另一个是()V

参考

  • [1] 深入理解Java虚拟机 周志明
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值