【Java八股面试系列】JVM-class文件结构

Class文件结构总结

根据 Java 虚拟机规范,Class 文件通过 ClassFile 定义,有点类似 C 语言的结构体。我们之前都是使用javap命令来对字节码文件进行反编译查看的,我们可以使用WinHex软件(Mac平台可以使用010 Editor)来以十六进制查看字节码文件。

image-20240129153116062

通过分析ClassFile的内容,我们可以知道Class文件的组成如下:

image-20240204102438701

下面这张图是通过 IDEA 插件 jclasslib 查看的,你可以更直观看到 Class 文件结构。

img

使用 jclasslib 不光可以直观地查看某个类对应的字节码文件,还可以查看类的基本信息、常量池、接口、属性、函数等信息。

魔数(Magic Number)

image-20240129153325220

首先,我们可以看到,前4个字节(共32位)组成了魔数(其实就是表示这个文件是一个JVM可以运行的字节码文件,除了Java以外,其他某些文件中也采用了这种魔数机制来进行区分,这种方式比直接起个文件扩展名更安全)

字节码文件的魔数为:CAFEBABE

Class文件版本号

面4个字节存储的是字节码文件的版本号,注意前两个是次要版本号(现在基本都不用了,都是直接Java8、Java9这样命名了),后面两个是主要版本号,这里我们主要看主版本号,比如上面的就是34,注意这是以16进制表示的,我们把它换算为10进制后,得到的结果为:34 -> 3*16 + 4 = 52,其中52代表的是JDK8编译的字节码文件(51是JDK7、50是JDK6、53是JDK9,以此类推)

注意:jdk版本号是向下兼容的

常量池

紧接着主次版本号之后的是常量池,常量池的数量是 constant_pool_count-1常量池计数器是从 1 开始计数的,将第 0 项常量空出来是有特殊考虑的,索引值为 0 代表“不引用任何一个常量池项”)。

常量池主要存放两大常量:字面量和符号引用。字面量比较接近于 Java 语言层面的的常量概念,如文本字符串、声明为 final 的常量值等。而符号引用则属于编译原理方面的概念。包括下面三类常量:

  • 类和接口的全限定名

  • 字段的名称和描述符

  • 方法的名称和描述符

常量池中每一项常量都是一个表,这 14 种表有一个共同的特点:开始的第一位是一个 u1 类型的标志位 -tag 来标识常量的类型,代表当前这个常量属于哪种常量类型。

类型标志描述
CONSTANT_Utf8_info1UTF-8编码格式的字符串
CONSTANT_Integer_info3整形字面量(第一章我们演示的很大的数字,实际上就是以字面量存储在常量池中的)
CONSTANT_Class_info7类或接口的符号引用
CONSTANT_String_info8字符串类型的字面量
CONSTANT_Fieldref_info9字段的符号引用
CONSTANT_Methodref_info10方法的符号引用
CONSTANT_MethodType_info16方法类型
CONSTANT_NameAndType_info12字段或方法的部分符号引用

访问标志(Access Flag)

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

类访问和属性修饰符:

image-20240204104544745

我们自定义了一个类,然后进行javap反编译,得到的访问标志

image-20240204104738456

当前类(This Class)、父类(Super Class)、接口(Interfaces)索引集合

Java 类的继承关系由类索引、父类索引和接口索引集合三项确定。类索引、父类索引和接口索引集合按照顺序排在访问标志之后,

类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名,由于 Java 语言的单继承,所以父类索引只有一个,除了 java.lang.Object 之外,所有的 Java 类都有父类,因此除了 java.lang.Object 外,所有 Java 类的父类索引都不为 0。

类的全限定名(Fully Qualified Class Name)是在编程中,一个类的完整名称,包括其所在的包(package)名称。例如,如果有一个类Examplecom.example包中,那么这个类的全限定名就是com.example.Example

接口索引集合用来描述这个类实现了那些接口,这些被实现的接口将按 implements (如果这个类本身是接口的话则是extends) 后的接口顺序从左到右排列在接口索引集合中。

字段表集合(Fields)

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

field info(字段表) 的结构:

字段表的结构

  • access_flags: 字段的作用域(public ,private,protected修饰符),是实例变量还是类变量(static修饰符),可否被序列化(transient 修饰符),可变性(final),可见性(volatile 修饰符,是否强制从主内存读写)。

  • name_index: 对常量池的引用,表示的字段的名称;

  • descriptor_index: 对常量池的引用,表示字段和方法的描述符;

  • attributes_count: 一个字段还会拥有一些额外的属性,attributes_count 存放属性的个数;

  • attributes[attributes_count]: 存放具体属性具体内容。

上述这些信息中,各个修饰符都是布尔值,要么有某个修饰符,要么没有,很适合使用标志位来表示。而字段叫什么名字、字段被定义为什么数据类型这些都是无法固定的,只能引用常量池中常量来描述。

方法表集合(Methods)

methods_count 表示方法的数量,而 method_info 表示方法表。

Class 文件存储格式中对方法的描述与对字段的描述几乎采用了完全一致的方式。方法表的结构如同字段表一样,依次包括了访问标志、名称索引、描述符索引、属性表集合几项。

method_info(方法表的) 结构:

方法表的结构

方法表的 access_flag 取值:

方法表的 access_flag 取值

注意:因为volatile修饰符和transient修饰符不可以修饰方法,所以方法表的访问标志中没有这两个对应的标志,但是增加了synchronizednativeabstract等关键字修饰方法,所以也就多了这些关键字对应的标志

属性表集合(Attributes)

在 Class 文件,字段表,方法表中都可以携带自己的属性表集合,以用于描述某些场景专有的信息。与 Class 文件中其它的数据项目要求的顺序、长度和内容不同,属性表集合的限制稍微宽松一些,不再要求各个属性表具有严格的顺序,并且只要不与已有的属性名重复,任何人实现的编译器都可以向属性表中写 入自己定义的属性信息,Java 虚拟机运行时会忽略掉它不认识的属性。

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

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

相关文章

Java:JDK8新特性(Stream流)、File类、递归 --黑马笔记

一、JDK8新特性(Stream流) 接下来我们学习一个全新的知识,叫做Stream流(也叫Stream API)。它是从JDK8以后才有的一个新特性,是专业用于对集合或者数组进行便捷操作的。有多方便呢?我们用一个案…

【GO语言卵细胞级别教程】04.GO函数介绍

【GO语言卵细胞级别教程】04.GO函数介绍 目录: 【GO语言卵细胞级别教程】04.GO函数介绍0.创建项目1.函数的引入2.注意事项3.详细介绍3.1 形参介绍 0.创建项目 创建目录 执行命令加载模块 cd 02.gostudy目录下 1.进入目录下 cd 02.gostudy 2.初始化模块变量 go …

LabVIEW伺服阀性能参数测试

LabVIEW伺服阀性能参数测试 伺服阀作为电液伺服系统中的核心元件,其性能参数的准确测试对保证系统整体性能至关重要。开发了一种基于LabVIEW软件开发的伺服阀性能参数测试系统,提高测试的自动化程度和精确性,同时降低操作复杂度和成本。 传…

MATLAB环境下一维时间序列信号的同步压缩小波包变换

时频分析相较于目前的时域、频域信号处理方法在分析时变信号方面,其主要优势在于可以同时提供时域和频域等多域信号信息,并清晰的刻画了频率随时间的变化规律,已被广泛用于医学工程、地震、雷达、生物及机械等领域。 线性时频分析方法是将信…

CS50x 2024 - Lecture 2 - Arrays

00:00:00 - Introduction 00:01:01 - Story Time 00:06:03 - Compiling make本身并不是编译器,实际上是一个自动运行编译器的程序,如c语言的clang clang -o hello hello.csrc/ $ clang -o hello hello_world.c /usr/bin/ld: /tmp/hello_world-67f51…

python+django高校教务选课成绩系统v0143

系统主要实现了以下功能模块: 本课题使用Python语言进行开发。基于web,代码层面的操作主要在PyCharm中进行,将系统所使用到的表以及数据存储到MySQL数据库中 使用说明 使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并…

Minecraft的红石教程之电梯

一.前言 我记得是上初中的时候,就看到了这类电梯。现在我在看现在这类电梯的相关视频,大多是盗用创意未能领会其中的红石运作规律,于是我就删繁就简写了这篇。 二.步骤 1.材料 粘性活塞,黏液块,红石,红…

什么是CDR数字音频广播

一、什么是数字音频广播 CDR(China DigilalRadio),即中国数字音领广播,是运用广播数字化技术,通过对音领信号进行信源编码、信道编码和载波调制传输,来实现数字音频广播业务和数据业务的播出。CDR与传统的FM调频广播相比&#xff…

SAP-PP-01-004物料主数据MRP视图参数

一、MRP1 MRP组 系统运行的 mrp 控制参数的组别。包含物料主数据中的一些 MRP 参数字段及工厂运行 MRP 控制设置参数,例如策略组、消耗模式、重计划期间、计划区间、计划时界、BOM 展开、计划订单转换的采购申请(PR)类型等。 工厂特定的物料…

你的立身之本是什么?

去年发生的一切,大到疫情、政治经济形势、行业的萎靡和震荡,小到身边的跳槽、裁员、公司倒闭……似乎都在告诉我们: 当冲击到来的时候,它是不会提前跟你打招呼的。 接下来的10年,我们所面临的不确定性,比起…

Mac电脑到手后的配置

一、Homebrew 1、Homebrew安装 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 桌面的Old_Homebrew文件夹,没有你需要的可以删除。 2、Homebrew卸载 /bin/zsh -c "$(curl -fsSL https://gitee.com/c…

C语言函数(三):数组和函数实现扫雷游戏

目录 1.扫雷游戏的分析和设计1.1.扫雷游戏的功能说明1.2.游戏的分析与设计1.2.1 数据结构的分析1.2.2 文件结构设计 2.扫雷游戏的代码实现 1.扫雷游戏的分析和设计 1.1.扫雷游戏的功能说明 使用控制台实现经典的扫雷游戏游戏可以通过菜单实现继续玩游戏或者退出游戏扫雷的棋盘…

ssm+vue的医药垃圾分类管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频: ssmvue的医药垃圾分类管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结…

【Linux】Linux下的基本指令

Linux下的基本指令 Linux 的操作特点:纯命令行ls 指令文件 pwd命令Linux的目录结构绝对路径 / 相对路径,我该怎么选择? cd指令touch指令mkdir指令(重要)rmdir指令rm 指令(重要)man指令&#xff…

RocketMQ(二):领域模型(生产者、消费者)

1 生产者(Producer) 本节介绍Apache RocketMQ 中生产者的定义、模型关系、内部属性、版本兼容和使用建议。 1.1 定义 生产者是Apache RocketMQ 系统中用来构建并传输消息到服务端的运行实体。 生产者通常被集成在业务系统中,将业务消息按照要…

【MySQL】字符串函数的学习

🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​💫个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-J7VN4RbrBi51ozap {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

kali最新最简单安装

之前都是用iso镜像文件的 今年好多东西都删库了,所有还是要主要资源的保存 去官网找下载 一般来说都是用虚拟机的 下载完会是一个压缩文件, 解压,然后操作之前需要先下载虚拟机 打开方式用虚拟机打开 kali就按装好了

Spring Boot3统一结果封装

⛰️个人主页: 蒾酒 🔥系列专栏:《spring boot实战》 🌊山高路远,行路漫漫,终有归途。 目录 前置条件 封装目的 常用格式 定义返回结果枚举类 定义返回结果封装类 对返回结果封装 测试封装 前置条件 已…

「daily updating」k3s + openfaas serverless bench 踩坑指南持续更新中

OpenFaas从入门到实战 – 踩坑指南 | k3dOpenFaas | deploy your first python function https://blog.alexellis.io/first-faas-python-function/ https://docs.openfaas.com/deployment/kubernetes/ 搭建环境:第一种方法失败,第二种方法…

【SpringBootStarter】自定义全局加解密组件

【SpringBootStarter】 目的 了解SpringBoot Starter相关概念以及开发流程实现自定义SpringBoot Starter(全局加解密)了解测试流程优化 最终引用的效果&#xff1a; <dependency><groupId>com.xbhog</groupId><artifactId>globalValidation-spring…