深入理解 JVM Class文件格式(七)
本专栏列前面的一系列博客, 对Class文件中的一部分数据项进行了介绍。 本文将会继续介绍class文件中未讲解的信息。 先回顾一下上面一篇文章。 在上一篇博客中, 我们介绍了:
this_class 对当前类的描述
super_class 对当前类的超类的描述
interfaces_count 当前类直接实现的接口的数量或当前接口直接继承的接口的数量
interfaces 对当前类或当前接口直接实现或继承的所有接口的描述
下面继续介绍class文件中的其他信息。
class文件中的fields_count和fields
fields_count描述的是当前的类中定义的字段的个数, 注意, 这里包括静态字段, 但不包括从父类继承的字段。 如果当前class文件是由一个接口生成的, 那么这里的fields_count描述的是接口中定义的字段, 我们知道, 接口中定义的字段默认都是静态的。此外要说明的是, 编译器可能会自动生成字段, 也就是说, class文件中的字段的数量可能多于源文件中定义的字段的数量。 举例来说, 编译器会为内部类增加一个字段, 这个字段是指向外围类的对象的引用。
位于fields_count下面的数据叫做fields, 可以把它看做一个数组, 数组中的每一项是一个field_info 。这个数组中一共有fields_count个field_info , 每个field_info都是对一个字段的描述。 下面我们详细讲解field_info的结构。 每个field_info的结构如下:
(1)access_flags
其中access_flags占两个字节, 描述的是字段的访问标志信息。 这里就不在详细介绍了, 下面给出一张表格(该表格来自《深入Java虚拟机》):
(2)name_index
access_flags下面的两个字节是name_index, 这是一个指向常量池的索引, 它描述的是当前字段的字段名。 这个索引指向常量池中的一个CONSTANT_Utf8_info数据项。 这个CONSTANT_Utf8_info数据项中存放的字符串就是当前字段的字段名。
(3)descriptor_index
name_index下面的两个字节叫做descriptor_index , 它同样是一个指向常量池的索引, 它描述的是当前字段的描述符。 这个索引指向常量池中的一个CONSTANT_Utf8_info数据项。 这个CONSTANT_Utf8_info数据项中存放的字符串就是当前字段的描述符(关于字段描述符, 在前面的博客中已经有过详细的讲解, 如果不明白, 请参考前面的博客:深入理解JVM Class文件格式(二))。
(4)attributes_count和attributes
descriptor_index 下面是attributes_count和attributes 。 这是对当前字段所具有的属性的描述。 这里的属性和源文件中的属性不是同一个概念, 在源文件测层面中, 属性是字段的另一种叫法, 希望读者不要疑惑。读者也不要轻视class文件中的属性, 这些属性可以描述很多的信息。 我们会在后面的文章中进行介绍。
attributes_count表示这个字段有几个属性。attributes 可以看成一个数组, 数组中的每一项都是一个attribute_info , 每个attribute_info 表示一个属性, 数组中一共有attributes_count个属性。可以出现在filed_info中的属性有三种, 分别是ConstantValue, Deprecated, 和 Synthetic。 这些属性会在后面的文章中进行介绍。
下面我们以代码的形式进行解释, 源码如下:
package com.jg.zhang;public class Programer extends Person{private Computer computer;public Programer(Computer computer){this.computer = computer;}public void doWork(){computer.calculate();}
}
反编译之后, 常量池中会有如下信息(这里省略了大部分无关信息):
Constant pool:.........
.........#5 = Utf8 computer#6 = Utf8 Lcom/jg/zhang/Computer;.........
.........{private com.jg.zhang.Computer computer;flags: ACC_PRIVATE.........
.........}
从反编译的结果可以看出, 源文件中定义了一个Computer类型的字段computer, 并且是private的。 然后常量池中有这个字段的字段名和描述符。 其中常量池第五项的CONSTANT_Utf8_info是字段名, 第六项的CONSTANT_Utf8_info是该字段的描述符。这里有一点需要说明, 在反编译Programer.class时,由于computer是私有的, 要加- private选项, 否则的话, 虽然常量池中有字段引用信息, 但是不会输出字段信息, 即下面这两行不会输出:
private com.jg.zhang.Computer computer;
flags: ACC_PRIVATE
如果在javap中加入 - private选项, 那么就会有上面两行的输出。 使用的命令如下:
javap -c -v -private -classpath . com.jg.zhang.Programer
根据反编译的结果,可以下面给出示意图, 该图说明了与computer相对应的field_info是如何引用常量池的 ( 其中虚线范围内表示常量池):
class文件中的methods_count和methods
fields下面的信息是methods_count和methods 。 methods_count描述的是当前的类中定义的方法的个数, 注意, 这里包括静态方法, 但不包括从父类继承的方法。 如果当前class文件是由一个接口生成的, 那么这里的methods_count描述的是接口中定义的抽象方法的数量, 我们知道, 接口中定义的方法默认都是公有的。此外需要说明的是, 编译器可能会在编译时向class文件增加额外的方法, 也就是说, class文件中的方法的数量可能多于源文件中由用户定义的方法。 举例来说: 如果当前类没有定义构造方法, 那么编译器会增加一个无参数的构造函数; 如果当前类或接口中定义了静态变量, 并且使用初始化表达式为其赋值, 或者定义了static静态代码块, 那么编译器在编译的时候会默认增加一个静态初始化方法 。
位于methods_count下面的数据叫做methods , 可以把它看做一个数组, 数组中的每一项是一个method_info 。这个数组中一共有methods_count个method_info , 每个method_info 都是对一个方法的描述。 下面我们详细讲解method_info 的结构。 每个method_info 的结构如下, 几乎和field_info的结构是一样的:
(1)access_flags
其中access_flags占两个字节, 描述的是方法的访问标志信息。 这里就不在详细介绍了, 下面给出一张表格(该表格来自《深入Java虚拟机》):
(2)name_index
access_flags下面的两个字节是name_index, 这是一个指向常量池的索引, 它描述的是当前方法的方法名。 这个索引指向常量池中的一个CONSTANT_Utf8_info数据项。 这个CONSTANT_Utf8_info数据项中存放的字符串就是当前方法的方法名。
(3)descriptor_index
name_index下面的两个字节叫做descriptor_index , 它同样是一个指向常量池的索引, 它描述的是当前方法的描述符。 这个索引指向常量池中的一个CONSTANT_Utf8_info数据项。 这个CONSTANT_Utf8_info数据项中存放的字符串就是当前方法的描述符(关于方法描述符, 在前面的博客中已经有过详细的讲解, 如果不明白, 请参考前面的博客: 深入理解JVM Class文件格式(二))。
(4)attributes_count和attributes
descriptor_index 下面是attributes_count和attributes 。 这是对当前方法所具有的属性的描述。 这里的属性和源文件中的属性不是同一个概念, 在源文件测层面中, 属性是字段的另一种叫法, 希望读者不要疑惑。读者也不要轻视class文件中的属性, 这些属性可以描述很多的信息。 我们会在后面的文章中进行介绍。
attributes_count表示这个字段有几个属性。attributes 可以看成一个数组, 数组中的每一项都是一个attribute_info , 每个attribute_info 表示一个属性, 数组中一共有attributes_count个属性。可以出现在method_info 中的属性有四种, 分别是Code, Deprecated, Exceptions 和Synthetic。 在这几个属性中, 尤其是Code和Exceptions 非常重要, 这两个属性对于在class文件中完整描述一个方法起着至关重要的作用, 其中Code属性中存放方法的字节面指令,Exceptions 属性是对方法声明中抛出的异常的描述 。 这两属性以及其他一些属性, 会在下一篇文章中详细介绍, 敬请关注。
介绍完了每个method_info的结构, 下面我们以代码来说明, 还是使用上面的源码:
package com.jg.zhang;public class Programer extends Person{private Computer computer;public Programer(Computer computer){this.computer = computer;}public void doWork(){computer.calculate();}
}
反编译之后, 常量池中会有如下信息(这里省略了大部分无关信息):
Constant pool:.........#7 = Utf8 <init>#8 = Utf8 (Lcom/jg/zhang/Computer;)V.........#12 = Utf8 ()V.........#19 = Utf8 doWork{.........public com.jg.zhang.Programer(com.jg.zhang.Computer);flags: ACC_PUBLIC.........public void doWork();flags: ACC_PUBLIC.........
}
由反编译结果可以看出, 该类中定义了两个方法, 其中一个是构造方法, 一个是doWork方法, 且这两个方法都是public的。 这两个方法的描述信息都存放在常量池。 其中第7项的CONSTANT_Utf8_info为构造方法的方法名, 第8项的CONSTANT_Utf8_info为构造方法的方法描述符, 第19项的CONSTANT_Utf8_info为doWork方法的方法名, 第12项的CONSTANT_Utf8_info为doWork方法的方法描述符。
根据常量池中的信息, 可以得出如下的示意图, 该示意图形象的说明了class文件中的method_info是如何引用常量池中的数据项来描述当前类中定义的方法的。 图中虚线范围内表示常量池所在的区域:
总结
到此为止, 我们就介绍完了class文件中的fields和methods, 进行一下总结。
fields是对当前类中定义的字段的描述, 其中每个字段使用一个field_info表示, fields中有fields_count个field_info。
methods是对当前类或者接口中声明的方法的描述, 其中每个方法使用一个method_info表示, methods中有methods_count个method_info。
在下一篇博客中, 将会介绍class文件中的各个属性, 敬请关注。
https://my.oschina.net/u/3892023/blog/2961140
深入理解 JVM Class文件格式(七)相关推荐
- 深入理解 JVM Class文件格式(九)
经过前八篇关于class文件的博客, 关于class文件格式的内容也基本上讲完了. 本文是关于class文件格式的最后一篇. 在这篇博客中, 将会讲解关于方法的几个属性. 理解这篇博客的内容, 对于理 ...
- 深入理解 JVM Class文件格式(八)
在本专栏的第一篇文章 深入理解Java虚拟机到底是什么 中, 我们主要讲解了什么是虚拟机, 这篇博客是对JVM的一个概述. 在随后的几篇文章中,一直在讲解class文件格式. 在今天这篇博客中, 将会 ...
- 深入理解 JVM Class文件格式(五)
(8) CONSTANT_Class_info 常量池中的一个CONSTANT_Class_info, 可以看做是CONSTANT_Class数据类型的一个实例. 他是对类或者接口的符号引用. 它描述 ...
- 深入理解 JVM Class文件格式(三)
** JVM常量池中各数据项类型详解 ** 关于常量池的大概内容, 已经在 深入理解 JVM Class文件格式(一) 中讲解过了, 这篇文章中还介绍了常量池中的11种数据类型. 本文的任务是详细讲解 ...
- 深入理解 JVM Class文件格式(十)
到此, 所有关于class文件格式的重要内容都已经讲解完了, 不敢说面面俱到, 但是敢说大部分重要的内容都包含在内了.前前后后用了9篇博客来专门讲解class文件结构, 为什么花那么多的时间和精力来介 ...
- 深入理解 JVM Class文件格式(六)
经过前几篇文章, 终于将常量池介绍完了, 之所以花这么大的功夫介绍常量池, 是因为对于理解class文件格式,常量池是必须要了解的, 因为class文件中其他地方,大量引用了常量池中的数据项. 对于还 ...
- 深入理解JVM类文件格式
我们知道Java最有名的宣传口号就是:"一次编写,到处运行(Write Once,Run Anywhere)",而其平台无关性则是依赖于JVM, 所有的java文件都被编译成字节码 ...
- 深入理解 JVM Class文件格式(二)
** class文件中的特殊字符串 ** 特殊字符串是常量池中符号引用的一部分,包括三种: 类的全限定名, 字段和方法的描述符, 特殊方法的方法名. 下面我们就分别介绍这三种特殊字符串. (1) 类的 ...
- 深入理解 JVM Class文件格式(一)
** 一.JVM体系结构 ** ** 二.class格式文件概述 ** class文件是一种8位字节的二进制流文件, 各个数据项按顺序紧密的从前向后排列, 相邻的项之间没有间隙, 这样可以使得clas ...
最新文章
- c4d教程-太空火车站场景创作视频教程Skillshare – Create A Space Train Scene With Cinema 4D Redshift Render
- 在windows XP运行3660路由器仿真器
- placeholder在不同浏览器下的表现及兼容方法
- 20140710文安c++面试总结
- JZOJ 5377. 【NOIP2017提高A组模拟9.19】开拓
- c语言 结构体_颖儿教你学C语言结构体,全面讲解,让程序小白玩转结构体编程...
- SAP License:SAP Business One 与SAP R/3的区别
- LeetCode-三数之和
- Windows无法安装到这个磁盘,选中的磁盘具有MBR分区表的解决方法
- win10相机计算机无法使用,Win10相机打不开 报错“0xa00f4244”要怎么解决?
- 解析经纬度,将度分转成度
- spark报错:Cannot overwrite a path that is also being read from.
- Interactive Speech and Noise Modeling for Speech Enhancement
- php ua解析,UA识别有什么用?
- 深入浅出内存马(一)
- 高分口碑神作《诡秘之主》《剑来》是第四届橙瓜网络文学奖大热门
- 输入汉字获得拼音(VB.net)
- HIS接口--LIS 与 HIS 跳转URL
- 十个好用的iOS开发辅助工具与资源
- 慢跑在一座陌生的城市
热门文章
- mysql为什么添加索引_当我添加新索引时,为什么MySQL中索引的基数保持不变?
- eltree ref什么时候有_Vue3响应式系统源码解析-Ref篇
- 计算机整个文稿应用回顾主题,《计算机应用基础》精品课程电子教案-PowerPoint 2003...
- 爱因斯坦为什么不是普通人?看他怎么喝茶就明白了,差距太明显了!没法比.......
- 男生的哪个“不要”是真的不要?
- 拉屎能赚钱?在马桶上月入过万?原来卫生间里还有这么多隐藏福利,超模君都惊了……
- “Python简直万能!”拜托快醒醒!
- 快速成长为数据挖掘高手的秘诀
- android 只能输入汉字,EditText限制输入的几种方式及只显示中文汉字的做法
- vscode函数跳转插件_人生苦短,我们为 Cocos Creator 开发的插件和工具