第六章 类文件结构

这章涉及记忆性的东西太多。

下面简要讲一下一些主要的内容,关于属性表的内容则省略,虽然貌似也挺重要,但是这方面的知识点太多。

如图所示Class类文件的结构按照从上往下排序依次也对应着class二进制文件里的顺序。

下面则是书上内容的一些摘要:

6.1 Class文件
  1. Class文件是一组以8字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件中,中间没有添加任何分隔符若遇到需要占用8字节以上空间的数据时,则会按照高位在前的方式分割成若干组8位字节进行存储。
  2. Class文件格式采用一种类似于C语言结构体的伪结构来存储,这种结构只有两种数据类型:无符号数和表。

那么无符号数和表又是什么呢?
无符号数属于基本的数据类型,以u1,u2,u4,u8来分别代表1个字节,2个字节,4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值、或者按照UTF-8编码构成字符串值
表是由多个无符号数或其他表作为数据项构成的复合数据类型,所有表都习惯性地以“_info”结尾,整个Class文件本质上就是一张表。

6.2 魔数(magic Number)

Class文件的头4个字节,作用:确定这个文件是否为一个能被虚拟机接受的Class文件。值为:0xCAFEBABE(咖啡宝宝)

这个好理解,比如EXE文件打开前面都也会有一个标记,jpg这些格式也是存在这种标记的。

6.3 版本号

紧接着魔数的4个字节。第5,6字节是次版本号,第7,8字节是主版本号

编译器版本 -target参数 十六进制版本号 十进制版本号
JDK 1.7.0 -target 1.6 00 00 00 32 51.0
6.4 常量池

常量池是占用Class文件空间最大的数据项目之一,也是在Class文件中第一个出现的表类型数据项目。其中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)
那么字面量(Literal)和符号引用(Symbolic References)又是什么呢?
1.字面量比较接近JAVA语言层面的常量概念,如文本字符串,final常量值
2.符号引用属于编译原理方面的概念,其包含下面三类常量:类和接口的全限定名(Fully Qualified Name)、字段的名称和描述符(Descriptor)、方法的名称和描述符

虽然解释了一下符号引用,那么描述符又是什么呢?

描述符:描述符的作用是用来描述字段的数据类型、方法的参数列表和返回值。

例如: 定义java.lang.String[][]的二维数组江北记录为"[[Ljava/lang/String",一个整形数组 int[]将被记录为"[I"

而方法比如int indexOf(char[] source int start),会被记录为([CI)I

如上面例子基本类型则直接首字母大写即可

6.5 访问标志(access_flag)

用于识别一些类或接口层次的访问信息,包括:这个Class是类还是接口,是否定义为public类型,是否定义为abstract类型,如果是类的话,是否被声明为final,等等。

6.6 类索引、父类索引、接口索引

类索引和父类索引都是一个u2类型的数据,接口索引是一组u2类型的数据,用来指向常量池中的数据

其中类索引和父类索引一直,

接口索引则是一个数组紧跟在interfaces_count一个接口个数的后面,名为interfaces的数组,它包含了对每个由该类或者接口直接实现(注:只包含直接出现在implements、extends子句中的父接口)的父接口的常量池索引。

两个字节为this_class项,它是一个对常量池的索引。在this_class位置的常量池入口必须为CONSTANT_Class_info表。该表由两个部分组成——标签和name_index。标签部分是一个具有CONSTANT_Class值的常量,在name_index位置的常量池入口为一个包含了类或接口全限定名的CONSTANT_Utf8_info表。

如图所示,可以看得清楚一些:

this_class的2个字节指向常量池的CONSTANT_Class_info表,而具体的信息则保持在CONSTANT_Utf8_info表中,在CONSTANT_Class_info有name_index项指向具体的表项。

6.7 字段表(field_info)

字段表用于描述接口或者类中声明的变量。包括类级变量或者实例级变量,但不包括方法内部声明的变量。

标示字符 含义
B 基本类型byte
C 基本类型char
S 基本类型short
I 基本类型int
F 基本类型float
D 基本类型double
J 基本类型long
Z 基本类型boolean
V 无返回值的void
L,如com/max/ComputerClass 对象类型

对于数组类型的描述,举例(描述符): 
java.lang.String[][] ---> [[Ljava/lang/String;
int[] ---> [I
即每一个维度将使用一个前置的"["字符来描述

首先是名为fields_count的计数,它是类变量和实例变量的字段的数量总和。在这个计数后面的是不同长度的field_info表的序列(fields_count指出了序列中有多少个field_info表)。每个fields_info表包含固定的3个属性,第一个是access_flags他表示字段或者方法的修饰权限,第二个name_index则对应常量池中的字段的简单名字描述,第三个descriptor_index则对应常量池中的描述符。之后还有一个attributes_count和attributes表示属性表,用来存储额外的一些信息,字段则可以存储初始化的一些信息,而方法则指向属性表中的字节码。

在fields列表中,不列出从超类或者父接口继承而来的字段。

6.8 方法表

和字段表很像。

对于方法的描述,举例:
void walk() ---> ()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
即遵循的规范是:先参数列表,后返回值。参数列表按照参数的严格顺序放在一组小括号"()"之内,数据类型用与之对应的符号来表示。

属性表略。

时间: 2024-12-21 14:26:21

第六章 类文件结构的相关文章

第六章 类文件结构(读深入理解jvm虚拟机,随记)

6.2  无关性的基石 标题为什么是无关性基石呢.时至今日,商业机构和开源机构已经在java语言之外发展出一大批在java虚拟机上运行的语言.如Clojure,Groovy,Scala等. java虚拟机不和包括java在内的任何语言绑定,它只与“Class文件”这种特定的二进制文件格式有所关联.  java程序(*.java)------>javac编译器------>字节码文件----->java虚拟机. 6.3  Class类文件的结构 如果想比较深入的了解虚拟机,那么这部分是不能

深入理解java虚拟机第二版(六)类文件结构

一.class类文件的结构 Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件之中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在. 根据Java虚拟机规范的规定,Class文件格式采用一种类似于C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号数和表. 无符号数属于基本的数据类型,以u1.u2.u4.u8来分别代表1个字节.2个字节.4个字节和8个字节的无符号数,无符号

第六章 类

类 介绍 传统的JavaScript程序使用函数和基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员来讲就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来的. 从ECMAScript 2015,也就是ECMAScript 6开始,JavaScript程序员将能够使用基于类的面向对象的方式. 使用TypeScript,我们允许开发者现在就使用这些特性,并且编译后的JavaScript可以在所有主流浏览器和平台上运行,而不需要等到下个JavaScript版本 类 clas

第6章 类文件结构

6.1 概述 计算机只认识0和1,传统的语言直接交给操作系统去执行,所以他们不能像Java一样,一次编译到处运行.Java编译后的代码是由虚拟机执行,编译后的结果是平台中立的格式. 6.2 无关性的基石 各种平台下Java编译后的格式都是一样的,所以称为平台中立的,这个格式就是字节码(Byte Code).Java虚拟机只认识字节码即class文件,所以虚拟机也可以执行别的语言,只要这些语言编译后的代码是class文件. 6.3 Class类文件的结构 主要介绍class文件的结构,以jdk1.

第六章类(三)实例字段

只记录回忆点 面向对象设计的一个核心部分是分组数据来建立特定结构. 在面向对象术语中,在类中存储数据的变量称为成员变量.这个术语在C#中很好理解,但更标准.更符合规范的术语是字段,它是与包容类型关联的具名存储单元. 实例字段是在类的级别上声明的变量,用于存储与对象关联的数据. 声明实例字段 访问实例字段 原文地址:https://www.cnblogs.com/158-186/p/11976965.html

第六章类(六)属性2命名规范

只记录回忆点 自动实现的属性 从C#3.0起属性语法有了简化版本. 在属性中声明支持字段,并用取值方法和赋值方法来获取和设置该字段.由于这是十分常见的设计,而且代码比较琐碎: 所以,现在允许在声明属性时不添加取值或赋值方法,也不声明任何支持字段. 一切都自动实现.简化了写法,也使代码更易读. 此外,如未来需添加一些额外的代码,比如要在赋值方法中进行验证,那么虽然要修改现在的属性声明来包含实现,但调用它们的代码不必进行任何修改. 属性和字段的设计规范 一般原则是方法代表行动,而属性代表数据. 避免

第六章类(七)属性3提供属性验证、只读和只写属性、取值和赋值方法的访问修饰符

只记录回忆点 如果为LastName赋了无效的值,代码就会抛出异常.拦截赋值,并通过字段风格的API对参数进行验证,这是属性的优点之一. 一个好的实践是从属性的实现中访问属性的支持字段.换言之,要一直使用属性,不要直接调用字段. 可移除属性的取值方法或赋值方法来改变属性的可访问性. 只有赋值方法的属性是只写属性,这种情况较罕见.C#6.0开始支持只读自动实现的属性. 设计规范 如果属性值不变,要创建只读属性: 不要提供只写属性,也不要让赋值方法的可访问性比取值方法更宽松: 原文地址:https:

第六章类(十九)readonly

readonly英文译义是只读属性,在上篇与const的对比,是说 1 在运行时为readonly字段赋值的,看到编译出来的CIL代码中readonly字段还是变量. 同样是字段(面对对象的术语),const修饰是常量的意思,那么,又为何有readonly的出现呢? 难道就是因为它是在运行时赋值的嘛? 我们在之前的文字中理解过const从意思上讲是常量的意思,就是要描述不随着时间推移发生变化的事物. 2 readonly就是只读的意思,另外它只能在构造函数中赋值或者声明时给它赋值,所以它是只能只

【WPF学习】第二十六章 Application类——应用程序的生命周期

原文:[WPF学习]第二十六章 Application类--应用程序的生命周期 在WPF中,应用程序会经历简单的生命周期.在应用程序启动后,将立即创建应用程序对象,在应用程序运行时触发各种应用程序事件,你可以选择监视其中的某些事件.最后,当释放应用程序对象时,应用程序将结束. 一.创建Application对象 使用Application类的最简单方式是手动创建它.下面的示例演示了最小的程序:在应用程序入口(Main()方法)处创建名为MainWindow的窗口,并启动一个新的应用程序: 在本质