深入理解Java虚拟机(2)-.Class文件格式(一)
来源:互联网 发布:linux wps 切换输入法 编辑:程序博客网 时间:2024/06/07 17:11
Class文件在Java体系结构中的位置和作用
在上一篇博客中, 大致讲解了Java虚拟机的体系结构和执行原理。 本篇博客主要讲解能够被JVM识别, 加载并执行的class文件的格式。
对于理解JVM和深入理解Java语言, 学习并了解class文件的格式都是必须要掌握的功课。 原因很简单, JVM不会理解我们写的Java源文件, 我们必须把Java源文件编译成class文件, 才能被JVM识别, 对于JVM而言, class文件相当于一个接口, 理解了这个接口, 能帮助我们更好的理解JVM的行为;另一方面, class文件以另一种方式重新描述了我们在源文件中要表达的意思, 理解class文件如何重新描述我们编写的源文件, 对于深入理解Java语言和语法都是很有帮助的。 另外, 不管是什么语言, 只要能编译成class文件, 都能被JVM识别并执行, 所以class文件不仅是跨平台的基础, 也是JVM跨语言的基础, 理解了class文件格式, 对于我们学习基于JVM的其他语言会有很大帮助。
总之, 在整个Java技术体系结构中, class文件处于中间的位置, 对于理解整个体系有着承上启下的作用。 如图所示:
Class文件格式概述
类型名称数量u4magic1u2minor_version1u2major_version1u2constant_pool_count1cp_infoconstant_poolconstant_pool_count - 1u2access_flags1u2this_class1u2super_class1u2interfaces_count1u2interfacesinterfaces_countu2fields_count1field_infofieldsfields_countu2methods_count1method_infomethodsmethods_countu2attribute_count1attribute_infoattributesattributes_count
下面对class文件中的每一项进行详细的解释。
class文件中的魔数和版本号
(1) magic
在class文件开头的四个字节, 存放着class文件的魔数, 这个魔数是class文件的标志,他是一个固定的值: 0XCAFEBABE 。 也就是说他是判断一个文件是不是class格式的文件的标准, 如果开头四个字节不是0XCAFEBABE, 那么就说明它不是class文件, 不能被JVM识别。
(2)minor_version 和 major_version
紧接着魔数的四个字节是class文件的此版本号和主版本号。 随着Java的发展, class文件的格式也会做相应的变动。 版本号标志着class文件在什么时候, 加入或改变了哪些特性。 举例来说, 不同版本的javac编译器编译的class文件, 版本号可能不同, 而不同版本的JVM能识别的class文件的版本号也可能不同, 一般情况下, 高版本的JVM能识别低版本的javac编译器编译的class文件, 而低版本的JVM不能识别高版本的javac编译器编译的class文件。 如果使用低版本的JVM执行高版本的class文件, JVM会抛出java.lang.UnsupportedClassVersionE
class文件中的常量池概述
在class文件中, 位于版本号后面的就是常量池相关的数据项。 常量池是class文件中的一项非常重要的数据。 常量池中存放了文字字符串, 常量值, 当前类的类名, 字段名, 方法名, 各个字段和方法的描述符, 对当前类的字段和方法的引用信息, 当前类中对其他类的引用信息等等。 常量池中几乎包含类中的所有信息的描述, class文件中的很多其他部分都是对常量池中的数据项的引用,比如后面要讲到的this_class, super_class, field_info, attribute_info等, 另外字节码指令中也存在对常量池的引用, 这个对常量池的引用当做字节码指令的一个操作数。 此外, 常量池中各个项也会相互引用。
class文件中的项constant_pool_count的值为1, 说明每个类都只有一个常量池。 常量池中的数据也是一项一项的, 没有间隙的依次排放。常量池中各个数据项通过索引来访问, 有点类似与数组, 只不过常量池中的第一项的索引为1, 而不为0, 如果class文件中的其他地方引用了索引为0的常量池项, 就说明它不引用任何常量池项。class文件中的每一种数据项都有自己的类型, 相同的道理,常量池中的每一种数据项也有自己的类型。 常量池中的数据项的类型如下表:
常量池中数据项类型类型标志类型描述CONSTANT_Utf81UTF-8编码的Unicode字符串CONSTANT_Integer3int类型字面值CONSTANT_Float4float类型字面值CONSTANT_Long5long类型字面值CONSTANT_Double6double类型字面值CONSTANT_Class7对一个类或接口的符号引用CONSTANT_String8String类型字面值CONSTANT_Fieldref9对一个字段的符号引用CONSTANT_Methodref10对一个类中声明的方法的符号引用CONSTANT_InterfaceMethodref11对一个接口中声明的方法的符号引用CONSTANT_NameAndType12对一个字段或方法的部分符号引用
每个数据项叫做一个XXX_info项, 比如, 一个常量池中一个CONSTANT_Utf8类型的项, 就是一个CONSTANT_Utf8_info 。除此之外, 每个info项中都有一个标志值(tag), 这个标志值表明了这个常量池中的info项的类型是什么, 从上面的表格中可以看出, 一个CONSTANT_Utf8_info中的tag值为1, 而一个CONSTANT_Fieldref_info中的tag值为9 。
Java程序是动态链接的, 在动态链接的实现中, 常量池扮演者举足轻重的角色。 除了存放一些字面量之外, 常量池中还存放着以下几种符号引用:
(1) 类和接口的全限定名
(2) 字段的名称和描述符
(3) 方法的名称和描述符
在详细讲解常量池中的各个数据项之前, 我们有必要先了解一下class文件中的特殊字符串, 因为在常量池中, 特殊字符串大量的出现,这些特殊字符串就是上面说的全限定名和描述符。 要理解常量池中的各个数据项, 必须先了解这些特殊字符串。
- 深入理解Java虚拟机(2)-.Class文件格式(一)
- 深入理解Java Class文件格式(一)
- 深入理解Java Class文件格式(一)
- 深入理解Java Class文件格式(一)
- 深入理解Java Class文件格式(一)
- 深入理解Java Class文件格式(一)
- 深入理解Java虚拟机(3)-.Class文件格式(二)
- 深入理解Java虚拟机(4)-.Class文件格式(三)
- 深入理解Java虚拟机(5)-.Class文件格式(四)
- 深入理解Java虚拟机(6)-.Class文件格式(五)
- 深入理解Java虚拟机(7)-.Class文件格式(六)
- 深入理解Java虚拟机(8)-.Class文件格式(七)
- 深入理解java class文件格式
- 深入理解Java Class文件格式
- 深入理解Java Class文件格式
- [Java]深入理解Java Class文件格式(一)
- 深入理解java语言的class文件格式(一)
- 深入理解Java Class文件格式(二)
- D
- js 模拟百度文库评分
- Dictionary转Json(序列化)
- iOS-AppIcon及LaunchImage整套设置
- SpringMVC中定时器继承Task后无法对service注入问题 收藏 Pig-man 发表于 1年前 阅读 1863 收藏 1 点赞 2 评论 0 330元/年抢阿里云香港云服务器,节省8
- 深入理解Java虚拟机(2)-.Class文件格式(一)
- hdoj 1090
- PF_RING开发指南 安装指南
- Logstash input output filter插件总结
- SQLite
- 【Oracle 12c ASM专题】Flex Diskgroup相关概念
- 使用面向对象思想建立一个学生管理系统
- MFC显示颜色选择对话框
- c++中的friend