《玻璃丝夹芯板项目可研报告》由会员分享,可在线阅读,更多相关《玻璃丝夹芯板项目可研报告(8页珍藏版)》请在金锄头文库上搜索。
1、一、JavaJava ClassClass 文件是什么文件是什么The JavaTM Virtual Machine Specification(Second Edtion)中有 表述:Java Class 文件由 8 位字节流组成,所有的 16 位、32 位和 64 位数据分 别通过读入 2 个、4 个和 8 个字节来构造,多字节数据总是按照 Big-endian 顺 序来存放,即高位字节在前(放在低地址)。每个 Class 文件都包含且仅包含 一个 Java 类型(类或者接口)。或许,The JavaTM Virtual Machine Specification中的表述不够明 确,那么我
2、们可以参考一下Inside the Java Virtual Machine(Second Edtion)中的表述:Java Class 文件特指以。class 为后缀名的 Java 虚拟机可 装载的文件。分析一下两者的表述,我觉得都不够全面、不够明确。我是这么定义的: Java Class 文件就是指符合特定格式的字节流组成的二进制文件。这个特定的 格式就是指第二节要讨论的 Class 文件格式,亦即在The JavaTM Virtual Machine Specification中定义的 Class 文件格式。从另一个角度来说,这个 特定格式就是指 JVM 能够识别、能够装载的格式。为什么
3、这么说呢?因为 JVM 在装载 class 文件时,要进行 class 文件验证,以保证装载的 class 文件内容 符合正确的内部结构。这个内部结构指的就是这个特定格式,只要是符合这个 特定格式的 Class 文件都是合法的、规范的 Class 文件,都是 JVM 能够装载的 Class 文件。如果觉得这样的表述还是不够明确,我只能建议你读完这篇文章 之后再回头来理解看看了 J为了讨论方便,在下文中将对这两个参考资料做个简记:1)The Java Virtual Machine Specification(Second Edtion)简 记为JVM Spec(2nded)。2)Inside
4、the Java Virtual Machine(Second Edtion) 简记为 Inside JVM(2nded)。二、Java Class 文件的格式在讲 Class 文件的格式之前,要介绍三个概念:1)数据类型:JVM Spec(2nded)中指出,Java Class 文件的数据用 自己定义的一个数据类型集来表示,即 u1,u2,u4,分别用于表示一个无符号类 型的、占 1,2,4 个字节的数据。在Inside JVM(2nded)一书中,作者把这 个数据类型集称之为 Class 文件的基本类型,本人觉得比较形象,便于理解。 所以,在本文中,我们也用基本类型来表示 Java Cl
5、ass 文件的数据。2)表:根据JVM Spec(2nded)中的定义,表(table)由项(定义见 3)组成,用于几种 Class 文件结构中。JVM Spec(2nded)中指出,Java Class 文件格式用一个类似于 C 结构的记号编写的伪结构来表示。这个伪结构 指的就是这里的表,例如下面的 ClassFile 表就是这种伪结构的一个典型例子, 下文中所有的表都是指这种伪结构的表。表的大小是可变的,这是因为它的组 成部分项是可变的。注意;这里的可变是针对 Class 层次而言的,即在不同的 Class 文件中该项的大小可能不一样的,但是对于每一个具体的 Class 文件来 说,这个项
6、的大小又是一定的,因而这个表的大小也是一定的。那么,项为什 么是可变的呢?请看下面的分析。3)项:描述 Java Class 文件格式的结构的内容称为项(items)。每个项 都有自己的类型和名称。项的类型可能是基本类型,也可能是一个表的名字, 这种项都是一些数组项。数组项的每一个元素都是一个表,这个表同顶层的 ClassFile 表一样,也都是一种伪结构,也都是由一些项构成的,而且这些表 不一定是同一种格式的,因此数组项也可以看作一个可变大小的结构流 J.这些 表对于该数组项来说就是子项,当然子项可能还有子项(目前子项的深度最多 就两层)。项的名称,没有什么好说的,就是JVM Spec(2n
7、ded)中指定的 一些名称。另外,项也是有大小的,对于没有子项的项来说,其大小是固定的; 对于有子项的项来说,其大小是可变的。在一个具体的 Class 文件中,一个可 变项(数组)的大小都会在其前一项中指定,为什么会是这样的呢?因为JVM Spec(2nded)中就是这么定义的!在 Class 文件中,每个项按规范中定义好 的顺序存储在 Class 文件中,相邻的项之间没有任何间隔,连续的项(数组) 也是按顺序存储,不进行填充或者对齐,这样可以使 Class 文件紧凑。好了,我想这三个概念我已经解释地比较清楚了,下面开始正式解析 Class 文件的格式。首先要来解析一下 ClassFile 表
8、结构,这是JVM Spec(2nded)中定义 的 Class 文件最外层的结构,换言之,就是 Class 文件的格式。ClassFile 表结构ClassFile u4 magic;u2 minor_version;u2 major_version;u2 constant_pool_count;cp_info constant_poolconstant_pool_count-1;u2 access_flags;u2 this_Class;u2 super_Class;u2 interfaces_count;u2 interfacesinterfaces_count;u2 fields_cou
9、nt;field_info fieldsfields_count;u2 methods_count;method_info methodsmethods_count;u2 attributes_count;attribute_info attributesattributes_count;ClassFile 表结构由 16 个不同的项组成,其中的各项可以简要地分析如下:(1) magic每个 Class 文件的前 4 个字节被称为它的魔数(magic number): 0xCAFEBABE.魔数的作用在于:可以轻松地分辨出 Java Class 文件和非 Java Class 文件。(如果一个
10、文件不是以 0xCAFEBABE 开头,它就肯定不是 Java Class 文件,因为它不符合规范 J)。当 Java 还称为“Oak“的时候,这个魔数就 已经定下来了,它预示了 Java 这个名字的出现。魔数的来历请大家自己查阅 J(2) minor_version 和 major_versionClass 文件的下面 4 个字节包含了次、主版本号。通常只有给定主版本号 和一系列次版本号后,Java 虚拟机才能够读取 Class 文件。如果 Class 文件的 版本号超出了 Java 虚拟机所能够处理的有效范围,Java 虚拟机将不会处理该 Class 文件。例如 J2SE5.0 版本的虚拟
11、机就不能执行由 J2SE6.0 版本的编译器 编译出来的 Class 文件。(3) constant_pool_count版本号后面的项是 constant_pool_count 即常量池计数项,该项的值必须 大于零,它给出该 Class 文件中常量池列表项的元素个数,这个计数项包括了 索引为 0 的 constant_pool 表项,但是该表项不出现在 Class 文件的 constant_pool 列表中,因为它被保留为 Java 虚拟机内部实现使用了,因此常量池列表的元素个数 constant_pool_count-1,各个常量池表项的索引值分别为 1 到 constant_pool_c
12、ount-1.注:在这里,有几个术语需要解释一下,常量池即为 constant_pool,常量 池列表就是指 constant_pool ,常量池表项即指常量池列表中的某一个具体 的表项(元素)。这些常量池表项的可能类型如下述的 cp_type 表所示:cp_type入口类型 标志值CONSTANT_Class 7CONSTANT_Fieldref 9CONSTANT_Methodref 10CONSTANT_InterfaceMethodref 11CONSTANT_String 8CONSTANT_Integer 3CONSTANT_Float 4CONSTANT_Long 5CONSTA
13、NT_Double 6CONSTANT_NameAndType 12CONSTANT_Utf8 1(4) constant_pool constant_pool_count 项下面是 constant_pool 项,即常量池列表,其 中存储了该 ClassFile 结构及其子结构中引用的各种常量,诸如文字字符串、 final 变量值、类名和方法名等等。在 Java Class 文件中,常量池表项是用一 个 cp_info 结构来描述的,常量池列表就是由 constant_pool_count-1 个连续 的、可变长度的 cp_info 表结构构成的 constant_pool 数组。为什么是
14、constant_pool_count-1 个 constant_pool 的原因,在上面已经解释了。每一 个常量池表项都是一个变长结构,其通常格式如下所示:cp_infocp_info 表的 tag 项是一个无符号的 byte 类型值,它表明了 cp_info 表的 类型和格式,具体的 tag 类型见上表。需要说明的是,cp_info 只是一个抽象的概念,在 Class 文件中,它表现 为一系列具体的、形如 CONSTANT_Xxxx_info 的 constant_pool 结构,其具体的 格式由 cp_info 表的 tag 项(即第一个字节)来确定。不同的 cp_info 表,其 in
15、fo项也是不一样的,例如,CONSTANT_Class_info 表的 info项为“u2 name_index“,而 CONSTANT_Utf8_info 表的 info项为“u2 length; u1 byteslength;“,显然,这两个 cp_info 表是不一样的,大小更是不一样的, 因而常量池表项的大小是可变的。由于常量池列表中的每个常量池表项的结构 是不一样,因此常量池列表的大小也是可变的。在 Class 文件中,常量池列表 项是一个可变长度的结构流。由 cp_info 表以及 cp_type 表我们可以知道,若 cp_info 表中 tag(标志) 项的值为 1 时,当前的 cp_info 就是一个 CONSTANT_Utf8_info 表结构,若 cp_info 表中 tag 项的值为 3,当前的 cp_info 就是一个 CONSTANT_Integer_info 表结构,其它情况类推。这些表的结构可以查阅JVM Spec(2nd