第六章 类文件结构

2、无关性的基石

3、Class类文件的结构

  • 任意一个有效的类或接口所应当满足的格式称为“Class文件格式”,实际上它
    并不一定以磁盘文件的形式存在
  • Class文件是一组以8位字节为基础单位的二进制流;当遇到需要占用8位字节以上空间的数据项时,则会按照高位在前[1]的方式分割成若干个8位字节进行存储
  • Class文件格式,只有两种数据类型:无符号数和表;
  • 无符号数属于基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串;
  • 表是由多个无符号数或者其他表作为数据项构成的复合数据类型
  • 表用于描述有层次关系的复合结构的数据,整个Class文件本质上就是一张表
  • 无论是无符号数还是表,当需要描述同一类型但数量不定的多个数据时,经常会使用一个前置的容量计数器加若干个连续的数据项的形式,这时称这一系列连续的某一类型的数据为某一类型的集合

【Class文件格式】


本章示例代码

package study6;

/**
 * Created by haicheng.lhc on 30/03/2017.
 *
 * @author haicheng.lhc
 * @date 2017/03/30
 */
public class TestClass {
    private int m;

    public int inc() {
        return m + 1;
    }
}

3.1 魔数与Class文件的版本

  • 每个Class文件的头4个字节称为魔数(Magic Number),它的唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件。
  • 紧接着魔数的4个字节存储的是Class文件的版本号:第5和第6个字节是次号(Minor Version),第7和第8个字节是主版本号(Major Version)。

3.2 常量池

  • 常量池可以理解为Class文件之中的资源仓库
  • 它是Class文件结构中与其他项目关联最多的数据类型
  • 是占用Class文件空间最大的数据项目之一
  • 还是在Class文件中第一个出现的表类型数据项目
  • 常量池的入口需要放置一项u2类型的数据,代表常量池容量计数值(constant_pool_count)。
  • 常量池中主要存放两大类常量:字面量(Literal)符号引用(Symbolic References)
  • 字面量比较接近于Java语言层面的常量概念,如文本字符串声明为final的常量值
  • 符号引用则属于编译原理方面的概念,包括了下面三类常量:

1、类和接口的全限定名(Fully Qualified Name)
2、字段的名称和描述符(Descriptor)
3、方法的名称和描述符

PS:Java代码在进行Javac编译的时候没有连接这一步,是在虚拟机加载Class文件的时候进行动态连接。Class文件中不会保存各个方法、字段的最终内存布局信息,因此这些字段、方法的符号引用不经过运行期转换的话无法得到真正的内存入口地址,也就无法直接被虚拟机使用。当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址之中

** 常量池中每一项常量都是一个表**

每一项的表结构

本章示例代码对应的常量表

~/vmstudy/src/main/java » javap -v study6.TestClass
Compiled from "TestClass.java"
public class study6.TestClass extends java.lang.Object
  SourceFile: "TestClass.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method       #4.#15; //  java/lang/Object."<init>":()V
const #2 = Field        #3.#16; //  study6/TestClass.m:I
const #3 = class        #17;    //  study6/TestClass
const #4 = class        #18;    //  java/lang/Object
const #5 = Asciz        m;
const #6 = Asciz        I;
const #7 = Asciz        <init>;
const #8 = Asciz        ()V;
const #9 = Asciz        Code;
const #10 = Asciz       LineNumberTable;
const #11 = Asciz       inc;
const #12 = Asciz       ()I;
const #13 = Asciz       SourceFile;
const #14 = Asciz       TestClass.java;
const #15 = NameAndType #7:#8;//  "<init>":()V
const #16 = NameAndType #5:#6;//  m:I
const #17 = Asciz       study6/TestClass;
const #18 = Asciz       java/lang/Object;

3.3 访问标志

在常量池结束之后,紧接着的两个字节代表访问标志(access_flags),这个标志用于识别一些类或者接口层次的访问信息,包括:这个Class是类还是接口是否定义为public类型是否定义为abstract类型如果是类的话,是否被声明为final等

3.4 类索引、父类索引与接口索引集合

  • 类索引(this_class)是一个u2类型的数据,用于确定这个类的全限定名
  • 父类索引(super_class)是一个u2类型的数据,父类索引用于确定这个类的父类的全限定名
  • 接口索引集合(interfaces)是一组u2类型的数据的集合
  • Class文件中由这三项数据来确定这个类的继承关系

3.5 字段表集合

  • 字段表(field_info)用于描述接口或者类中声明的变量
  • 字段(field)包括类级变量以及实例级变量,但不包括在方法内部声明的局部变量

access_flags可取值如下表

name_index是对常量池的引用,代表着字段的简单名称
descriptor_index是对常量池的引用,代表字段的描述符

“简单名称”、“描述符”以及前面出现过多次的“全限定名”这三种特殊字符串的概念。
全限定名,“org/fenixsoft/clazz/TestClass”是这个类的全限定名,仅仅是把类全名中的“.”替换成了“/”而已,为了使连续的多个全限定名之间不产生混淆,在使用时最后一般会加入一个“;”表示全限定名结束
简单名称是指没有类型和参数修饰的方法或者字段名称,inc()方法和m字段的简单名称分别是“inc”和“m”。
描述符的作用是用来描述字段的数据类型方法的参数列表(包括数量、类型以及顺序)和返回值

对于数组类型,每一维度将使用一个前置的“[”字符来描述,如一个定义
为“java.lang.String[][]”类型的二维数组,将被记录为:“[[Ljava/lang/String;”,一个整型数组“int[]”将被记录为“[I”
用描述符来描述方法时,按照先参数列表,后返回值的顺序描述,参数列表按照参数的严格顺序放在一组小括号“()”之内

void inc()的描述符为     "()V",
java.lang.String toString() 的描述符为       "()Ljava/lang/String;",
int indexOf(char[]source, int sourceOffset, int sourceCount,char[] target, int targetOffset, int targetCount, int fromIndex)的描述符为 "([CII[CIII)I"

3.6 方法表集合

  • 方法表的结构如同字段表一样,依次包括了访问标志(access_flags)、名称索引(name_index)、描述符索引(descriptor_index)、属性表集合(attributes)几项

3.7 属性表集合

  • 属性表(attribute_info)在前面的讲解之中已经出现过数次,在Class文件、字段表、方法表都可以携带自己的属性表集合,以用于描述某些场景专有的信息
  • 虚拟机规范定义的属性
  • Code属性Java程序方法体中的代码经过Javac编译器处理后,最终变为字节码指令存储在Code属性内。Code属性出现在方法表的属性集合之中,但并非所有的方法表都必须存在这个属性,譬如接口或者抽象类中的方法就不存在Code属性
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容