[转载更改] 简书 Class文件结构--常量池(一)

- 这篇文章讲Class格式文件的的魔数、版本号
- 字节码查看工具:WinHex
1. 全局规范
(1) 任何一个Class文件都对应着唯一一个类或接口的定义信息,但反过来说,类或接口并不一定都得定义在文件里(譬如类或接口也可以通过类加载器直接生成)。本章中,只是通俗地将任意一个有效的类或接口所应当满足的格式称为“Class文件格式”,实际上它并不一定以磁盘文件的形式存在。“Class文件”应当是一串二进制的字节流,无论以何种形式存在。
(2) Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件之中,当遇到需要占用8位字节以上空间的数据项时,则会按照高位在前(Big-Endian)的方式分割成若干个8位字节进行存储。无符号数据类型最大占8个字节。
-
(3) Class文件中存储数据的类型:无符号数和表。
无符号数(基本数据类型):以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值。
表(复合数据类型):是由多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯性地“_info”结尾。表用于描述有层次关系的复合结构的数据。表是一个统称,就好比把ArrayList、LinkedList、Set都是称为集合(Collection),但是每个集合的内部结构都是不同的,Class中有很多不同的表。如下图中cp_info类型,是表类型,但是它是一个固定结构的类型吗?不是,它好比Collection集合下的List集合,只是一类集合的统称,实际上cp_info表是14种具体表类型的统称,constant_pool_count-1指出了有多少个cp_info表,那到底是哪些具体的表,就需要具体看了。
-
(4) 整个Class文件本质上就是一张表,下表就是Class文件格式。Class中所有内容都在这些类型中定义了。
-
注:表中的数据项,无论是顺序还是数量,甚至于数据存储的字节序(Byte Ordering,Class文件中字节序为Big-Endian)这样的细节,都是被严格限定的,哪个字节代表什么含义,长度是多少,先后顺序如何,都不允许改变。
class文件格式class文件结构
-
-
(5) 无论是无符号数还是表,当需要描述同一类型但数量不定的多个数据时,经常会使用一个前置的容量计数器加若干个连续的数据项的形式,这时称这一系列连续的某一类型的数据为某一类型的集合。
如上表的描述常量池数据使用了一个constant_pool_count、多个constant_pool,其中constant_pool是表类型并且数量为constant_pool_count值减去1,把一个constant_pool_count和多个constant_pool数据项称为常量池集合
从Class文件格式中可以看出有:常量池集合、接口索引集合、字段表集合、方法表集合、属性表集合。
(6) 具体的Class文件案例,以下讲解会通过这个TestClass类的TestClass.class文件来分析。
package com.zlcook.clazz;
public class TestClass{
private int m;
public int inc(){
return m+1;
}
}
2. 魔数与Class文件的版本

- 由上表得Class文件的前三个数据类型存储了魔数(magic)、次版本号(minor_version)、主版本号(major_version)的值,数据类型分别为u4、u2、u2。共占8个字节。
2.1 魔数
-
魔数:0xCAFEBABE (16进制),值固定,唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件。
魔数
2.2 版本号
- Class文件版本号:次版本号组成u2+主版本号u2。共占4个字节。
- 高版本的JDK能向下兼容以前的版本的Class文件,但不能运行高版本的Class文件。
- JDK1.1的版本号为45.0-45.65535(10进制),之后每个大版本发布主版本号加1,如:JDK1.2:46.0~46.65535。



