`
Rolandz
  • 浏览: 6644 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java类文件的基本结构

阅读更多
欢迎来到“Under The Hood”第二期。上期我们讨论了抽象计算机JVM。如果你对JVM还很陌生,你可以去看看上期的文章。本期,我们稍稍窥探一下Java类文件的基本结构。

为旅行而生

Java类文件(.class文件)是一个为已编译Java程序仔细定义的格式。Java源代码被编译成能够被任何JVM加载和执行的类文件。在被JVM加载之前,类文件可能是由网络传输而来。

类文件是独立于底层平台的,所以适用于更多的地方。它们由简洁的JVM字节码组成,这样就能轻装上阵。类文件常常被压缩,以极快的速度通过网络,到达世界各地的JVM。

类文件里有什么?

Java类文件包含JVM需要知道的关于一个Java类或接口的一切。按照它们的出现次序,主要的部分有:魔法数(magic),版本号(version),常量池(constant pool),访问标示符区(access flags),当前类区(this class),超类区(super class),父接口区(interfaces),字段区(fields),方法列表区(methods),属性区(attributes)。

保存在类文件中的信息经常在长度上有变化,所以信息的实际长度在被加载之前不能被预测。例如,在方法区里的方法数目,类与类之间是不相同的,这取决于源代码中定义的方法个数。类文件中,这些信息的实际大小或长度,被安排在信息内容之前。这样,当类文件被JVM加载时,可变信息的长度首先被读取。一旦JVM知道信息的大小,它就能正确的读取实际的信息内容。

类文件中,不同的相邻信息之间通常没有空白或填充字符;一切都以字节(byte)边界对齐。这使得类文件很小,适合网络传输。

为了让JVM在加载类文件时,知道需要什么信息以及从哪里可以取得所需信息,类文件的各个组成部分的次序是严格定义的。例如,每个JVM都知道类文件的前8个字节由魔法数和版本号组成,常量池从第9个字节开始,访问标示符区紧跟在常量池后面。但是,因为常量池的长度是可变的,在读取完常量池之前,JVM是不知道访问标示符区具体从什么地方开始。一旦读取完常量池,JVM就知道接下来的2个字节就是访问标示符区。

魔法数(Magic)和版本号(Version)

每个类文件的开始4个字节都是0xCAFEBABE。这个神奇的数字让Java类文件更容易识别,因为类文件以外的文件几乎不可能也以这四个相同的字节开头。之所以称之为魔法数,是因为它可以被文件格式设计者们从帽子里拉出来(??)。对它仅有的要求是,不能被现实已有的文件格式占用。根据最初Java团队主要成员之一的Patrick Naughton所说,远在“Java”被当作Java语言的名称之前,这个神奇的数字就已经被选好了。我们当时在寻找一个有趣,独特并且很容易记住的数字。0xCAFEBABE作为漂亮的Peet’s Coffee的咖啡师的代称,能预示未来Java语言的名字,这完全是一个巧合。

类文件接下来的4个字节包含了大版本号(major version)和小版本号(minor version)。这些数字标识了特定类文件使用的类文件格式,让JVM可以验证类文件是否可以被载入。每个JVM都有一个它能载入的最大版本号,拒绝加载大于最大版本号的类文件。

常量池(Constant Pool)

类文件在常量池中保存与类或接口关联的常量。常量池中能看到的部分常量是字符串字面值(literal strings),final变量的值(final variable values),类名,接口名,变量名和变量类型,方法名和方法签名(method names and signatures)。方法签名由方法返回值类型(return type)和一组参数类型(argument types)组成。

常量池被组织成一个元素长度可变的数组。每个常量占据数组中的一个元素。在整个类文件中,常量通过指示它们在数组中位置的整型索引来引用。第一个常量的索引值是1,第二个是2,以此类推。常量池数组的元素个数写在常量池的前面,所以在加载类文件时,JVM知道它需要加载多少常量。

常量池中每个元素以指明自己类型的单字节标签(tag)开始。一旦JVM看到这个标签,就能知道接下来会遇到什么类型的常量。例如,如果看到一个表示字符串的标签,JVM会认为接下来2个字节就是字符串的长度,然后就是“长度”个字节组成的字符串。

在本文剩下的部分,我有时会用constant_pool[n]表示常量池数组的第n个元素。从常量池组织的像个数组来说,这是有道理的;但是请记住,这些元素具有不同的大小和类型,并且第一个元素的索引是1。

访问标识符区(Access Flags)

常量池之后的2个字节就是访问标示符,它表明该文件定义的是类还是接口;该类或接口是公开的(public)还是抽象的(abstract);如果是类,该类是不是final的。

当前类区(This class)

接下来2个字节是当前类区,它是常量池数组的索引。被当前类引用的常量constant_pool[this_class],包含两部分:单字节标签(tag)和双字节名称索引(name index)。标签等于CONSTANT_Class,一个表示本元素中包含类或接口信息的值。constant_pool[name_index]是一个包含类或接口名的字符串常量。

当前类部分稍稍揭示了常量池是怎么被使用的。当前类区本身只是一个常量池的索引。当JVM查找constant_pool[this_class]时,它找到一个用标签表明自己是一个CONSTANT_Class得元素。JVM知道CONSTANT_Class元素在标签(tag)之后,总是有一个叫名称索引(name index)的常量池双字节索引。然后它查找constant_pool[name_index],得到包含类或接口名的字符串。

超类区(Super class)

当前类区之后是超类区,也是2个字节的常量池索引。constant_pool[super_class]是CONSTANT_Class元素,它指向当前类所直接继承的超类名。

接口区(Interfaces)

接口区开头的2个字节,表示文件所定义的类(或接口)实现的接口数目。紧接着是一个数组,它包含了类所实现的每一个接口在常量池中的索引。
每个接口都是常量池中的CONSTANT_Class元素,它指向接口名。

字段区(Fields)

字段部分,以表示该类或接口包含的字段数的2个字节开始。字段是一个实例变量,或者是类或接口的类变量。接下来是一个以可变长结构为元素的数组,一个结构一个字段。每个结构都包含一个字段的相关信息,如字段名,字段类型,如果是final变量,还包括字段值。部分信息在结构当中,另一部分在常量池中由结构所指向的位置。

这部分仅有的字段,都是由定义在该类文件中的类或接口声明的变量;继承自超类或接口的字段不在此列。

方法区(Methods)

方法部分,以表示类或接口中方法数目的2字节开始。这个数目,只包含当前类显式定义的方法,不包括继承自超类的方法。数目之后是方法本身。

表示每个方法的结构包含方法相关的几条信息,包括方法描述符(method descriptor,包括返回值类型和参数列表),方法本地变量需要的栈字(stack words)数,方法操作数栈(operand stack)需要的最大栈字数,方法捕获的异常表,字节码序列和行号表。

属性区(Attributes)

排在最后的是属性区,它提供定义在类文件中的特定类或接口的一般信息。属性区以2字节的属性数目开始,然后是属性本身。比如一个表示源码属性的属性:它表示当前类被编译而来的源文件名。JVM会悄悄地忽略任何它们识别不了的属性。

本文译自:The Java class file lifestyle

原创文章,转载请注明: 转载自LetsCoding.cn
本文链接地址: Java类文件的基本结构
0
3
分享到:
评论

相关推荐

    Java类文件的基本结构_.docx

    Java类文件的基本结构_.docx

    JAVA_API1.6文档(中文)

    java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...

    数据结构JAVA实现

    JAVA实现链表 有序二叉树 队列的代码例子

    Java比较两个mysql数据库表结构的差异

    一个简单JAVA 小工程进行两个MYSQL数据库对象的比较,导入eclipse中,修改jdbc.properties文件中的JDBC信息,然后直接运行action包类中的main方法,生成EXCEL,excel中包含表,表中列,索引,函数过程差异比对结果。...

    java基本类库结构图.zip

    这是一个java常用类的目录结构图,因为类实在太多,一张图放不下,所以使用 Echarts 做成了 HTML 页面,直接打开压缩包里面的 html 文件即可,点击小圆点可以看到下一层目录.

    Java基础笔记,代码结构

    适合一些卖课程或者有学习过Java的人选。里面是Java一开始需要掌握的一些代码知识和常识,一些基础知识的笔记,Java代码的基本运用和代码里需要掌握的一些细节。

    JavaAPI1.6中文chm文档 part1

    java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...

    java程序结构

    java程序结构,从基本数据类型开始讲起...

    java源码包---java 源码 大量 实例

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    java类文件结构(笔记).docx

    无符号数属于基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号...表用于描述有层次关系的复核结构的数据,整个Class文件本质上就是一张表,它是由 小标 所示的数据项构成的:

    JAVA 2平台安全技术-结构,API设计和实现

    本书明确而详尽地阐述了Java平台安全性,探究了Java安全结构的内幕。本书首先概述了计算机和网络安全概念并解释了Java安全模型,并在此基础上,详细描述了Java 2平台中新增加的许多安全结构方面的措施,同时对Java...

    JAVA上百实例源码以及开源项目

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    java源码包4

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    Java程序的基本结构.pptx

    Java程序的基本结构学习目标 掌握Java程序的基本架构。 学会使用控制台输出语句。 理解Java程序的基本语法。我们首先通过一个简单的Java程序来了解程序的组成结构、语言要素和编程规范,建立程序的基本概念。初识...

    Java软件体系结构设计模式标准指南

    Java软件体系结构设计模式标准指南 压缩文档包括(PDF + PPT + 课程源代码 + chm文档) 第一部分 设计模式简介 第二部分 URL 第三部分 基本模式 第四部分 创建模式 第五部分 集合模式 第六部分 结构模式 第七部分 ...

    java数据结构课程设计java代码

    界面使用swing做的,也利用的一些文件来存储数据,希望对大家能够有所帮助

    125集专攻JAVA基础 JAVA零基础入门学习视频教程 动力节点JAVA视频教程.txt

    北京动力节点-Java编程零基础教程-032-Java基本语法-注释-文档注释.avi 北京动力节点-Java编程零基础教程-033-Java基本语法-注释-javadoc命令.avi 北京动力节点-Java编程零基础教程-034-Java基本语法-标识符.avi ...

    java源码包3

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    Java基础技术文档

    第03章 Java基本语法 第04章 Java与面向对象编程 第05章 Java的数据结构 第06章 字符串操作 第07章 接口和包 第08章 异常处理 第09章 Java的IO系统 第10章 多线程编程 第11章 Java小程序Applet 第12章 操作数据库 第...

Global site tag (gtag.js) - Google Analytics