首页 > 其他分享 >类文件结构

类文件结构

时间:2023-07-01 18:22:40浏览次数:37  
标签:info 文件 CONSTANT 常量 u2 索引 Class 结构

类文件结构

JVM 的“无关性”

谈论 JVM 的无关性,主要有以下两个:

  • 平台无关性:任何操作系统都能运行 Java 代码
  • 语言无关性: JVM 能运行除 Java 以外的其他代码

Java 源代码首先需要使用 Javac 编译器编译成 .class 文件,然后由 JVM 执行 .class 文件,从而程序开始运行。

JVM 只认识 .class 文件,它不关心是何种语言生成了 .class 文件,只要 .class 文件符合 JVM 的规范就能运行。 目前已经有 JRuby、Jython、Scala 等语言能够在 JVM 上运行。它们有各自的语法规则,不过它们的编译器 都能将各自的源码编译成符合 JVM 规范的 .class 文件,从而能够借助 JVM 运行它们。

Java 语言中的各种变量、关键字和运算符号的语义最终都是由多条字节码命令组合而成的, 因此字节码命令所能提供的语义描述能力肯定会比 Java 语言本身更加强大。 因此,有一些 Java 语言本身无法有效支持的语言特性,不代表字节码本身无法有效支持。

Class 文件结构

Class 文件是二进制文件,它的内容具有严格的规范,文件中没有任何空格,全都是连续的 0/1。Class 文件 中的所有内容被分为两种类型:无符号数、表。

  • 无符号数 无符号数表示 Class 文件中的值,这些值没有任何类型,但有不同的长度。u1、u2、u4、u8 分别代表 1/2/4/8 字节的无符号数。
  • 表 由多个无符号数或者其他表作为数据项构成的复合数据类型。

Class 文件具体由以下几个构成:

  • 魔数
  • 版本信息
  • 常量池
  • 访问标志
  • 类索引、父类索引、接口索引集合
  • 字段表集合
  • 方法表集合
  • 属性表集合

魔数

Class 文件的头 4 个字节称为魔数,用来表示这个 Class 文件的类型。

Class 文件的魔数是用 16 进制表示的“CAFE BABE”,是不是很具有浪漫色彩?

魔数相当于文件后缀名,只不过后缀名容易被修改,不安全,因此在 Class 文件中标识文件类型比较合适。

版本信息

紧接着魔数的 4 个字节是版本信息,5-6 字节表示次版本号,7-8 字节表示主版本号,它们表示当前 Class 文件中使用的是哪个版本的 JDK。

高版本的 JDK 能向下兼容以前版本的 Class 文件,但不能运行以后版本的 Class 文件,即使文件格式并未发生任何变化,虚拟机也必须拒绝执行超过其版本号的 Class 文件。

常量池

版本信息之后就是常量池,常量池中存放两种类型的常量:

  • 字面值常量

    字面值常量就是我们在程序中定义的字符串、被 final 修饰的值。

  • 符号引用

    符号引用就是我们定义的各种名字:类和接口的全限定名、字段的名字和描述符、方法的名字和描述符。

常量池的特点

  • 常量池中常量数量不固定,因此常量池开头放置一个 u2 类型的无符号数,用来存储当前常量池的容量。
  • 常量池的每一项常量都是一个表,表开始的第一位是一个 u1 类型的标志位(tag),代表当前这个常量属于哪种常量类型。

常量池中常量类型

类型 tag 描述
CONSTANT_utf8_info 1 UTF-8 编码的字符串
CONSTANT_Integer_info 3 整型字面量
CONSTANT_Float_info 4 浮点型字面量
CONSTANT_Long_info 5 长整型字面量
CONSTANT_Double_info 6 双精度浮点型字面量
CONSTANT_Class_info 7 类或接口的符号引用
CONSTANT_String_info 8 字符串类型字面量
CONSTANT_Fieldref_info 9 字段的符号引用
CONSTANT_Methodref_info 10 类中方法的符号引用
CONSTANT_InterfaceMethodref_info 11 接口中方法的符号引用
CONSTANT_NameAndType_info 12 字段或方法的符号引用
CONSTANT_MethodHandle_info 15 表示方法句柄
CONSTANT_MethodType_info 16 标识方法类型
CONSTANT_InvokeDynamic_info 18 表示一个动态方法调用点

对于 CONSTANT_Class_info(此类型的常量代表一个类或者接口的符号引用),它的二维表结构如下:

类型 名称 数量
u1 tag 1
u2 name_index 1

tag 是标志位,用于区分常量类型;name_index 是一个索引值,它指向常量池中一个 CONSTANT_Utf8_info 类型常量,此常量代表这个类(或接口)的全限定名,这里 name_index 值若为 0x0002,也即是指向了常量池中的第二项常量。

CONSTANT_Utf8_info 型常量的结构如下:

类型 名称 数量
u1 tag 1
u2 length 1
u1 bytes length

tag 是当前常量的类型;length 表示这个字符串的长度;bytes 是这个字符串的内容(采用缩略的 UTF8 编码)

访问标志

在常量池结束之后,紧接着的两个字节代表访问标志,这个标志用于识别一些类或者接口层次的访问信息,包括:这个 Class 是类还是接口;是否定义为 public 类型;是否被 abstract/final 修饰。

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

类索引和父类索引都是一个 u2 类型的数据,而接口索引集合是一组 u2 类型的数据的集合,Class 文件中由这三项数据来确定类的继承关系。类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名。

由于 Java 不允许多重继承,所以父类索引只有一个,除了 java.lang.Object 之外,所有的 Java 类都有父类,因此除了 java.lang.Object 外,所有 Java 类的父类索引都不为 0。一个类可能实现了多个接口,因此用接口索引集合来描述。这个集合第一项为 u2 类型的数据,表示索引表的容量,接下来就是接口的名字索引。

类索引和父类索引用两个 u2 类型的索引值表示,它们各自指向一个类型为 CONSTANT_Class_info 的类描述符常量,通过该常量总的索引值可以找到定义在 CONSTANT_Utf8_info 类型的常量中的全限定名字符串。

字段表集合

字段表集合存储本类涉及到的成员变量,包括实例变量和类变量,但不包括方法中的局部变量。

每一个字段表只表示一个成员变量,本类中的所有成员变量构成了字段表集合。字段表结构如下:

类型 名称 数量 说明
u2 access_flags 1 字段的访问标志,与类稍有不同
u2 name_index 1 字段名字的索引
u2 descriptor_index 1 描述符,用于描述字段的数据类型。 基本数据类型用大写字母表示; 对象类型用“L 对象类型的全限定名”表示。
u2 attributes_count 1 属性表集合的长度
u2 attributes attributes_count 属性表集合,用于存放属性的额外信息,如属性的值。

字段表集合中不会出现从父类(或接口)中继承而来的字段,但有可能出现原本 Java 代码中不存在的字段,譬如在内部类中为了保持对外部类的访问性,会自动添加指向外部类实例的字段。

方法表集合

方法表结构与属性表类似。

volatile 关键字 和 transient 关键字不能修饰方法,所以方法表的访问标志中没有 ACC_VOLATILE 和 ACC_TRANSIENT 标志。

方法表的属性表集合中有一张 Code 属性表,用于存储当前方法经编译器编译后的字节码指令。

属性表集合

每个属性对应一张属性表,属性表的结构如下:

类型 名称 数量
u2 attribute_name_index 1
u4 attribute_length 1
u1 info attribute_length

本文由mdnice多平台发布

标签:info,文件,CONSTANT,常量,u2,索引,Class,结构
From: https://www.cnblogs.com/wind-xwj/p/17519690.html

相关文章

  • 云服务器 搭建NFS 文件系统 用于解决负载均衡session 文件共享等
    解决的问题:如果多台服务器负载均衡用户没有根据TCP设置分配在一台服务器那么session无法共享文件无法共享一台服务器创建了文件另外一台也会同步创建1.搭建NFSServe注意:共享系统的服务端和客户端不能安装在同一台服务器上例如你做负载均衡的2台服务器内网ip 12.20.10......
  • JS传wav文件给后台
    <buttonid="recordButton">开始录制</button>letrecordButton=document.getElementById('recordButton');letmediaRecorder;//媒体实例letchunks=[];//语音文件letisRecording=false;//是正在录制还是停止录......
  • Redis数据结构——快速列表(quicklist)1
    Redis数据结构——快速列表(quicklist)一、什么是quicklistquicklist是Redis3.2版本以后针对链表和压缩列表进行改造的一种数据结构,是zipList和linkedList的混合体,相对于链表它压缩了内存。进一步的提高了效率。quicklist其实就是简单的双链表,但每个双链表节点中保存......
  • Redis数据结构——快速列表(quicklist)
    Redis数据结构——快速列表(quicklist)一、什么是quicklistquicklist是Redis3.2版本以后针对链表和压缩列表进行改造的一种数据结构,是zipList和linkedList的混合体,相对于链表它压缩了内存。进一步的提高了效率。quicklist其实就是简单的双链表,但每个双链表节点中保存......
  • 01修建结构
    1非结构化剪枝1.1.1细粒度剪枝细粒度剪枝是一种特定类型的剪枝方法,它指的是单个权重级别的剪枝。在细粒度剪枝中,模型中的每一个权重都会被独立地考虑是否需要被剪枝。这种方法的优点是可以非常精确地控制模型的大小和复杂性,因为可以精确地选择哪些权重需要被剪枝。然而,这也是一......
  • 10.11 定义枚举结构
    demo1在枚举类中定义成员属性与方法enumColor{ //枚举类 RED("红色"),GREEN("绿色"),BLUE("蓝色"); //枚举对象要写在首行 privateStringtitle;//成员属性 privateColor(Stringtitle){//构造方法初始化属性; this.title=title; } @Override publicStrin......
  • 分布式文件存储 - FastDFS 工具类
    一、FastDFSClientpackagecom.changgou.file.util;importorg.csource.common.NameValuePair;importorg.csource.fastdfs.*;importorg.slf4j.LoggerFactory;importorg.springframework.core.io.ClassPathResource;importjava.io.ByteArrayInputStream;importjav......
  • C/C++《数据结构课程设计》题目[2023-07-01]
    C/C++《数据结构课程设计》题目[2023-07-01]《数据结构课程设计》题目一、【大数四则运算】——线性表[习题描述]设计—个实现任意长的整数进行四则运算和幂次运算的演示程序。[基本要求]利用双向循环链表实现大数的存储,每个结点含一个整型变量。[实现提示]实现原理:任何一......
  • 13 | 为什么表数据删掉一半,表文件大小不变?
    13|为什么表数据删掉一半,表文件大小不变?参数innodb_file_per_table表数据既可以存在共享表空间里,也可以是单独的文件。这个行为是由参数innodb_file_per_table控制的:ON表示的是,每个InnoDB表数据存储在一个以.ibd为后缀的文件中OFF表示的是,表的数据放在系统共享表......
  • 什么是 SAP UI5 的 cldr json 文件
    SAPUI5是一个基于HTML5的UI开发框架,它允许开发人员构建功能丰富、易于维护和满足企业需求的应用程序。它是一个集成了各种UI控件、工具和库的强大框架,旨在简化企业级应用程序的开发过程。SAPUI5的一个重要特性是对国际化和本地化的支持,这意味着开发人员可以构建能够适应......