java中Class文件的文件格式

无关性的基石

计算机底层只能识别二进制,由CPU直接处理二进制,在底层上面是操作系统,在操作系统上面就是虚拟机,java有一个口号,“一次编写,到处运行”这个不太可能在操作系统层面上实现,不同的操作系统肯定将会长期并存发展,所以这个理想只能在“应用层”实现。

在虚拟机中使用字节码,而所有的指令都会转成字节码,传递给虚拟机

Class类文件的结构

class文件是一串严格有序无分隔符无对齐符二进制流

class文件伪结构如下

ClassFile {u4             magic;u2             minor_version;u2             major_version;u2             constant_pool_count;cp_info        constant_pool[constant_pool_count-1];u2             access_flags;u2             this_class;u2             super_class;u2             interfaces_count;u2             interfaces[interfaces_count];u2             fields_count;field_info     fields[fields_count];u2             methods_count;method_info    methods[methods_count];u2             attributes_count;attribute_info attributes[attributes_count];
}

在这里插入图片描述

魔数与 Class 文件的版本

每个Class文件的头四个字节称为魔数,他的作用是确定这个文件是否可以被虚拟机接受的Class文件

魔数的 4 个字节存储的是 Class 文件的版本号:第5和第 6个字节是次版本号,第 7 和第 8 个字节是主版本号

高版本的 JDK 能向下兼容以前版本的 Class 文件,但不能运行以后版本的 Class 文件

Class 文件格式采用一种类似于 C 语言结构体的伪结构来存 储数据,这种伪结构中只有两种数据类型:“无符号数”和“表”

  • 无符号数属于基本的数据类型,以 u1、u2、u4、u8 来分别代表 1 个字节、2 个字节、4 个字节 和 8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值
  • 表是由多个无符号数或者其他表作为数据项构成的复合数据类型

常量池

常量池可以比喻为 Class 文件里的资源仓库

在常量池的入口需要放置 一项 u2类型的数据,代表常量池容量计数值,这个从0开始不是1开始

常量池中主要存放两大类常量:字面量和符号引用

字面量就是java中的常量概念

符号引用属于编译原理方面的概念,主要包括下面的常量:

被模块导出或者开放的包

  • 类和接口的全限定名
  • 字段的名称和描述符
  • 方法的名称和描述符
  • 方法句柄和方法类型
  • 动态调用点和动态常量

在 Class 文件中不会保存各个方法、字段最终在内存中的 布局信息,这些字段、方法的符号引用不经过虚拟机在运行期转换的话是 无法得到真正的内存入口地址,也就无法直接被虚拟机使用的。当虚拟机做类加载时,将会从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址之中。

常量池中每一项常量都是一个表,他有17个类表,表示17种不同类型的常量

17 类表都有一个共同的特点,表结构起始的第一位是个 u1 类型的标志位,代表着当前常量属于哪种常量类型。

这17个表每一个表的结构都不一样各自有着完全独立的数据结构,首位都是tag来标记数据类型,后面的根据不同的需要设计不同

访问标志

在常量池结束之后,紧接着的 2 个字节代表访问标志

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

在这里插入图片描述

在这里插入图片描述

access_flags 中一共有 16 个标志位可以使用,当前只定义了其中 9 个,没有使用到的标志位要求一律为零

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

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

接口索引集合,入口的第一项 u2 类型的数据为接口计数器,表示索引表的容量。

字段表集合

描述接口或者类中声明的变量

字段中可以包含各种各样的修饰符,这些修饰符可以使用标志位处理,但是字段叫什么名字,什么类型是无法确定的,只能使用常量池中的常量来描述

在这里插入图片描述

在Class文件中字段表集合的第一个U2类型数据为容量计数器,即记录字段表集合数量,之后就是上面的表中内容

方法表集合

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

方法的定义通过过访问标志、名称索引、描述符索引来表达清楚,方法中的代码内容会经过Javac 编译器编译成字节码指令之后,存放在方法属性表集合中一个名为“Code”的属性里面

方法表集合和字段表集合一样在具体描述表之前会有一个u2类型数据描述方法表集合的大小,代表这个集合中有几个方法

属性表集合

属性表在前面的讲解之中已经出现过数次,Class 文件、字段表、方法表都可以携带自己的属性表集合,以描述某些场景专有的信息。

只要不与已有属性名重复,任何人实现的编译器都可以向属性表中写入自己定义的属性信息,Java 虚拟机运行时会忽略掉它不认识的属性。

对于每一个属性,它的名称都要从常量池中引用一个 CONSTANT_Utf8_info 类型的 常量来表示,而属性值的结构则是完全自定义的,只需要通过一个 u4 的长度属性去说 明属性值所占用的位数即可

在这里插入图片描述

总结

在这里插入图片描述

还是这张图

一个Class文件首先是四个字节的一个魔数用来表示是否可以被虚拟机接收,然后是版本号,次级版本号,然后是常量池中存储我们需要使用的数据,不光是编译前的数据还包括编译时的数据比如接口限定名等,在这里首先会使用一个u2的大小记录常量池大小然后在根据不同记录常量,在常量记录完毕之后是访问标识是一些类的访问信息,然后是类索引父类索引等,接下来是接口索引记录接口数量,然后会有一个接口池记录接口信息,接口记录完毕后面就是字段表,方法表,属性表的记录,这些表都有一个计数器记录大小

  • 魔数
  • 版本,次版本
  • 访问标志
  • 常量池
  • 类,父类,接口索引,
  • 字段表,方法表,属性表

字节码指令简介

Java 虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需的参数(称为操作数, Operand)构成。

指令集因为他的操作码只有一个数字所以他的操作码指令数不能超过256条,这样它在处理一些超过一个字节的数据时需要从字节中重建出具体的数据结构,他会损失掉一些性能,好处在于放弃了操作数长度对齐,省略掉大量的填充和间隔符号

字节码和数据类型

在java的指令集中,大部分指令都有包含其操作对应的数据类型信息,

对于大部分与数据类型相关的字节码指令,它们的**操作码助记符**中都有特殊的字符来表明专门为哪种数据类型服务:

  • i 代表对 int 类型的数据操作,
  • l 代表 long,s 代表 short,
  • b 代表 byte,c 代表 char,
  • f 代表 float,d 代表 double,
  • a 代表 reference。

也有一些指令的助记符没有明确指明操作类型的字母

因为操作集只有一个字节所以它没有设计所有的数据类型的操作码,Java 虚拟机的指令集对于特定的操作只提供了有限的类型相关指令去支持它,在处理的时候如果发现某一个数据类型没有对应的指令集会对其进行相关的扩展比如编译器会在编译期或运行期将 byte 和 short 类型的 数据带符号扩展为相应的 int 类型数据

加载和存储指令

加载和存储指令用于将数据在栈帧中的局部变量表和操作数栈之间来回传输,这类指令包括:

  • 将一个局部变量加载到操作栈:iload、iload_、lload、lload_、fload、 fload_、dload、 dload_、aload、aload_
  • 将一个数值从操作数栈存储到局部变量表:istore、istore_、lstore、 lstore_、fstore、 fstore_、dstore、dstore_、astore、astore_
  • 将一个常量加载到操作数栈:bipush、sipush、ldc、ldc_w、ldc2_w、aconst_null、 iconst_m1、 iconst_、lconst_、fconst_、dconst_
  • 扩充局部变量表的访问索引的指令:wide

指令助记符中,有一部分是以尖括号结尾的(例如 iload_),这些 指令助记符实际上代表了一组指令(例如 iload_,它代表了 iload_0、iload_1、 iload_2 和 iload_3 这几条指令)。这几组指令都是某个带有一个操作数的通用指令(例如 iload)的特殊形式,对于这几组特殊指令,它们省略掉了显式的操作数,不需要进行取 操作数的动作,因为实际上操作数就隐含在指令中。除了这点不同以外,它们的语义与 原生的通用指令是完全一致的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/52954.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

三重因素,巨人瘦身——从 IBM中国研发部裁员讲起

如何看待IBM中国研发部裁员?近日,IBM中国宣布撤出在华两大研发中心,引发了IT行业对于跨国公司在华研发战略的广泛讨论。这一决定不仅影响了众多IT从业者的职业发展,也让人思考全球化背景下中国IT产业的竞争力和未来发展方向。面对…

【CMake】使用CMake在VIsual Studio内构建多文件夹工程

一、配置准备 打开VIsual Studio,载入写好的 C M a k e l i s t s . t x t CMakelists.txt CMakelists.txt,在项目中添加以下文件: 创建一个文件夹 f u n c s funcs funcs,里面放入 f u n c . h func.h func.h、 f u n c . c p …

使用mlp算法对Digits数据集进行分类

程序功能 这个程序使用多层感知机(MLP)对 Digits 数据集进行分类。程序将数据集分为训练集和测试集,创建并训练一个具有两个隐藏层的 MLP 模型。训练完成后,模型对测试数据进行预测,并通过准确率、分类报告和混淆矩阵…

C语言刷题日记(附详解)(5)

一、选填部分 第一题: 下面代码在64位系统下的输出为( ) void print_array(int arr[]) {int n sizeof(arr) / sizeof(arr[0]);for (int i 0; i < n; i)printf("%d", arr[i]); } int main() {int arr[] { 1,2,3,4,5 };print_array(arr);return 0; } A . 1…

Arcgis实现面空间位置从东至西从南至北排序

效果 背景 工作项目中经常会遇到需要对网格进行编号,而编号是有一定原则的,比如空间位置从上到下从左到右,或者其它原则,那么都可以通过下面的方式来实现 1、准备数据 点shp文件,查看初始FID字段标注,目前是一个无序的状态 2、排序 字段选择空间字段,空间排序方法…

02请求响应(简单参数)

一、操作目的 前端通过post/get请求&#xff0c;传递给后端简单的数据&#xff0c;后端接收后在控制台打印出来&#xff0c;并将结果返回给前端页面展示出来。&#xff08;这里我们用postman来模拟前端页面&#xff0c;而非真实的通过编写前端代码&#xff0c;通过浏览器来展示…

STM32与ESP8266的使用

串口透传 “透传”通常指的是数据的透明传输&#xff0c;意思是在不对数据进行任何处理或修改的情况下&#xff0c;将数据从一个接口转发到另一个接口。值得注意的是要避免串口之间无限制的透明&#xff0c;可以采用互斥锁的方式进行限制使用方法 对USART1和USART3(用他俩举例…

【ArcGIS Pro实操第一期】研究区域制图-以粤港澳GBA地区为例

ArcGIS Pro实操第一期&#xff1a;研究区域制图-以粤港澳GBA地区为例 数据准备1 ArcGIS Pro绘制研究区域图1.1 基本处理1.2 导入数据并制图1.3 添加整饰要素 参考 数据准备 DEM高程数据市区边界文件&#xff08;.shp文件&#xff09; 目标成图如下&#xff1a; 1 ArcGIS Pr…

TalkSphere项目介绍

TalkSphere项目介绍 文章目录 TalkSphere项目介绍一、前言二、技术栈及开发环境三、主要功能&#xff08;一&#xff09;用户登录与注册&#xff08;二&#xff09;用户历史消息展示&#xff08;三&#xff09;在线用户实时聊天 四、结语 一、前言 在线聊天室作为一个虚拟社交…

《网络协议 - HTTP传输协议及状态码解析》

文章目录 一、HTTP协议结构图二、HTTP状态码解读1xx: 信息响应类2xx: 成功响应类3xx: 重定向类4xx: 客户端错误类5xx: 服务器错误类 一、HTTP协议结构图 二、HTTP状态码解读 HTTP状态码&#xff08;英语&#xff1a;HTTP Status Code&#xff09;是用以表示网页服务器超文本传…

安卓玩机工具-----无需root权限 卸载 禁用 删除当前机型app应用 ADB玩机工具

ADB玩机工具 ADB AppControl是很实用的安卓手机应用管理工具&#xff0c;无需root权限&#xff0c;通过usb连接电脑后&#xff0c;可以很方便的进行应用程序安装与卸载&#xff0c;还支持提取手机应用apk文件到电脑上&#xff0c;此外还有手机系统垃圾清理、上传文件等…

QUIC的loss detection学习

PTO backoff backoff 补偿 /ˈbkɒf/PTO backoff 是QUIC&#xff08;Quick UDP Internet Connections&#xff09;协议中的一种机制&#xff0c;用于处理探测超时&#xff08;Probe Timeout, PTO&#xff09;重传策略 它逐步增加探测超时的等待时间&#xff0c;以避免网络拥塞…

[网络]http请求中的URL,方法,header 和 http响应中的状态码

文章目录 一. http请求1. 认识URLurlencode 2. 认识方法应用场景构造http请求 2. 认识请求报头header 二. http响应1. 状态码 一. http请求 1. 认识URL 我们所说的"网址", 其实就是URL(Uniform Resource Locator 统⼀资源定位符) 1.协议方案名 常见的有http和http…

警惕!甲状腺病的早期“信号弹”,你捕捉到了吗?

在快节奏的现代生活中&#xff0c;健康问题往往被忽视&#xff0c;尤其是那些初期症状不明显、容易被误解或忽视的疾病。甲状腺&#xff0c;这个位于颈部下方、形状如蝴蝶的小腺体&#xff0c;虽然不起眼&#xff0c;却是人体内分泌系统中的重要一员&#xff0c;负责调节新陈代…

AIGC:python 文生图代码(python + stable-diffusion+ cuda)

解决什么问题 搭建一个文生图环境 + python文生图代码,通过输入prompt,生成图片 解决方法 文生图的代码比较简易,主要是搭建环境+下载文生图大模型 步骤一: 创建虚拟环境(用python 3.10版本,起得名字最好可以一看就知道Python的版本) conda create -n text2img3.10 py…

【RAG】RAG再进化?基于长期记忆的检索增强生成新范式-MemoRAG

前言 RAG现在工作很多&#xff0c;进化的也很快&#xff0c;再来看看一个新的RAG工作-MemoRAG。 文章提出&#xff0c;RAG在减少大模型对于垂类知识的问答幻觉上取得了不错的效果&#xff0c;也成为私域知识问答的一种范式。然而&#xff0c;传统RAG系统主要适用于明确信息需…

HTML5超酷炫的水果蔬菜在线商城网站源码系列模板1

文章目录 1.设计来源1.1 主界面1.2 商品列表界面1.3 商品详情界面1.4 其他界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/142059238 HTML5超酷炫的水果蔬菜在线商城网…

软件工程毕业设计开题汇总

文章目录 &#x1f6a9; 1 前言1.1 选题注意事项1.1.1 难度怎么把控&#xff1f;1.1.2 题目名称怎么取&#xff1f; 1.2 开题选题推荐1.2.1 起因1.2.2 核心- 如何避坑(重中之重)1.2.3 怎么办呢&#xff1f; &#x1f6a9;2 选题概览&#x1f6a9; 3 项目概览题目1 : 大数据电商…

Linux 开发工具(vim、gcc/g++、make/Makefile)+【小程序:进度条】-- 详解

目录 一、Linux软件包管理器 - yum&#xff08;ubuntu用apt代替yum&#xff09;1、Linux下安装软件的方式2、认识 yum3、查找软件包4、安装软件5、如何实现本地机器和云服务器之间的文件互传 二、Linux编辑器 - vim1、vim 的基本概念2、vim 下各模式的切换3、vim 命令模式各命令…

WebGL系列教程八(GLSL着色器基础语法)

目录 1 前言2 基本原则3 基本数据类型4 顶点着色器和片元着色器4.1 声明4.2 初始化项目4.3 赋值 5 结构体5.1 声明5.2 赋值 6 函数6.1 基本结构6.2 自定义函数6.3 常用内置函数 7 精度8 其他9 总结 1 前言 通过前七讲&#xff0c;我们已经见过了WebGL中的部分基础语法&#xff…