JVM——类文件结构
文章目录
- 一 概述
- 二 Class 文件结构总结
- 2.1 魔数
- 2.2 Class 文件版本
- 2.3 常量池
- 2.4 访问标志
- 2.5 当前类索引,父类索引与接口索引集合
- 2.6 字段表集合
- 2.7 方法表集合
- 2.8 属性表集合
一 概述
在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比较高效,而且,由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。
Clojure(Lisp 语言的一种方言)、Groovy、Scala 等语言都是运行在 Java 虚拟机之上。下图展示了不同的语言被不同的编译器编译成.class文件最终运行在 Java 虚拟机之上。.class文件的二进制格式可以使用 WinHex 查看。

可以说.class文件是不同的语言在 Java 虚拟机之间的重要桥梁,同时也是支持 Java 跨平台很重要的一个原因。
二 Class 文件结构总结
根据 Java 虚拟机规范,类文件由单个 ClassFile 结构组成:
ClassFile {u4 magic; //Class 文件的标志u2 minor_version;//Class 的小版本号u2 major_version;//Class 的大版本号u2 constant_pool_count;//常量池的数量cp_info constant_pool[constant_pool_count-1];//常量池u2 access_flags;//Class 的访问标记u2 this_class;//当前类u2 super_class;//父类u2 interfaces_count;//接口u2 interfaces[interfaces_count];//一个类可以实现多个接口u2 fields_count;//Class 文件的字段属性field_info fields[fields_count];//一个类会可以有多个字段u2 methods_count;//Class 文件的方法数量method_info methods[methods_count];//一个类可以有个多个方法u2 attributes_count;//此类的属性表中的属性数attribute_info attributes[attributes_count];//属性表集合
}
下面详细介绍一下 Class 文件结构涉及到的一些组件。
Class文件字节码结构组织示意图 (之前在网上保存的,非常不错,原出处不明):

2.1 魔数
u4 magic; //Class 文件的标志
每个 Class 文件的头四个字节称为魔数(Magic Number),它的唯一作用是确定这个文件是否为一个能被虚拟机接收的 Class 文件。
程序设计者很多时候都喜欢用一些特殊的数字表示固定的文件类型或者其它特殊的含义。
2.2 Class 文件版本
u2 minor_version;//Class 的小版本号u2 major_version;//Class 的大版本号
紧接着魔数的四个字节存储的是 Class 文件的版本号:第五和第六是次版本号,第七和第八是主版本号。
高版本的 Java 虚拟机可以执行低版本编译器生成的 Class 文件,但是低版本的 Java 虚拟机不能执行高版本编译器生成的 Class 文件。所以,我们在实际开发的时候要确保开发的的 JDK 版本和生产环境的 JDK 版本保持一致。
2.3 常量池
u2 constant_pool_count;//常量池的数量cp_info constant_pool[constant_pool_count-1];//常量池
紧接着主次版本号之后的是常量池,常量池的数量是 constant_pool_count-1(常量池计数器是从1开始计数的,将第0项常量空出来是有特殊考虑的,索引值为0代表“不引用任何一个常量池项”)。
常量池主要存放两大常量:字面量和符号引用。字面量比较接近于 Java 语言层面的的常量概念,如文本字符串、声明为 final 的常量值等。而符号引用则属于编译原理方面的概念。包括下面三类常量:
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
常量池中每一项常量都是一个表,这14种表有一个共同的特点:开始的第一位是一个 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_MothodType_info | 16 | 标志方法类型 |
| CONSTANT_MethodHandle_info | 15 | 表示方法句柄 |
| CONSTANT_InvokeDynamic_info | 18 | 表示一个动态方法调用点 |
.class 文件可以通过javap -v class类名 指令来看一下其常量池中的信息(javap -v class类名-> temp.txt :将结果输出到 temp.txt 文件)。
2.4 访问标志
在常量池结束之后,紧接着的两个字节代表访问标志,这个标志用于识别一些类或者接口层次的访问信息,包括:这个 Class 是类还是接口,是否为 public 或者 abstract 类型,如果是类的话是否声明为 final 等等。
类访问和属性修饰符:

我们定义了一个 Employee 类
package top.snailclimb.bean;
public class Employee {...
}
通过javap -v class类名 指令来看一下类的访问标志。

2.5 当前类索引,父类索引与接口索引集合
u2 this_class;//当前类u2 super_class;//父类u2 interfaces_count;//接口u2 interfaces[interfaces_count];//一个类可以实现多个接口
类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名,由于 Java 语言的单继承,所以父类索引只有一个,除了 java.lang.Object 之外,所有的 java 类都有父类,因此除了 java.lang.Object 外,所有 Java 类的父类索引都不为 0。
接口索引集合用来描述这个类实现了那些接口,这些被实现的接口将按 implements (如果这个类本身是接口的话则是extends) 后的接口顺序从左到右排列在接口索引集合中。
2.6 字段表集合
u2 fields_count;//Class 文件的字段的个数field_info fields[fields_count];//一个类会可以有个字段
字段表(field info)用于描述接口或类中声明的变量。字段包括类级变量以及实例变量,但不包括在方法内部声明的局部变量。
field info(字段表) 的结构:

- access_flags: 字段的作用域(
public,private,protected修饰符),是实例变量还是类变量(static修饰符),可否被序列化(transient 修饰符),可变性(final),可见性(volatile 修饰符,是否强制从主内存读写)。 - name_index: 对常量池的引用,表示的字段的名称;
- descriptor_index: 对常量池的引用,表示字段和方法的描述符;
- attributes_count: 一个字段还会拥有一些额外的属性,attributes_count 存放属性的个数;
- attributes[attributes_count]: 存放具体属性具体内容。
上述这些信息中,各个修饰符都是布尔值,要么有某个修饰符,要么没有,很适合使用标志位来表示。而字段叫什么名字、字段被定义为什么数据类型这些都是无法固定的,只能引用常量池中常量来描述。
字段的 access_flag 的取值:

2.7 方法表集合
u2 methods_count;//Class 文件的方法的数量method_info methods[methods_count];//一个类可以有个多个方法
methods_count 表示方法的数量,而 method_info 表示方法表。
Class 文件存储格式中对方法的描述与对字段的描述几乎采用了完全一致的方式。方法表的结构如同字段表一样,依次包括了访问标志、名称索引、描述符索引、属性表集合几项。
method_info(方法表的) 结构:

方法表的 access_flag 取值:

注意:因为volatile修饰符和transient修饰符不可以修饰方法,所以方法表的访问标志中没有这两个对应的标志,但是增加了synchronized、native、abstract等关键字修饰方法,所以也就多了这些关键字对应的标志。
2.8 属性表集合
u2 attributes_count;//此类的属性表中的属性数attribute_info attributes[attributes_count];//属性表集合
在 Class 文件,字段表,方法表中都可以携带自己的属性表集合,以用于描述某些场景专有的信息。与 Class 文件中其它的数据项目要求的顺序、长度和内容不同,属性表集合的限制稍微宽松一些,不再要求各个属性表具有严格的顺序,并且只要不与已有的属性名重复,任何人实现的编译器都可以向属性表中写 入自己定义的属性信息,Java 虚拟机运行时会忽略掉它不认识的属性。
相关文章:
JVM——类文件结构
文章目录 一 概述二 Class 文件结构总结2.1 魔数2.2 Class 文件版本2.3 常量池2.4 访问标志2.5 当前类索引,父类索引与接口索引集合2.6 字段表集合2.7 方法表集合2.8 属性表集合 一 概述 在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class …...
银河麒麟服务器v10 sp1 .Net6.0 上传文件错误
上一篇:银河麒麟服务器v10 sp1 部署.Net6.0 http https_csdn_aspnet的博客-CSDN博客 .NET 6之前,在Linux服务器上安装 libgdiplus 即可解决,libgdiplus是System.Drawing.Common原生端跨平台实现的主要提供者,是开源mono项目。地址…...
C#实现普通的语音播报
Windows有文字转语音功能,C#提供了调用的类库Interop.SpeechLib.dll 使用方法很简单,在你的项目中添加Interop.SpeechLib.dll引用,在类中引用: using SpeechLib;这里提供一个CVoice类 帮助实现语音播报 public class CVoice{pri…...
django中实现事务的几种方式
1.实现事务的三种方式 1.1 全局开启事务---> 全局开启事务,绑定的是http请求响应整个过程 DATABASES {default: {#全局开启事务,绑定的是http请求响应整个过程ATOMIC_REQUESTS: True, }} from django.db import transaction# 局部禁用事务 transac…...
【es6】具名组匹配
1、组匹配 正则表达式使用圆括号进行组匹配,如:const RE_DATE /(\d{4})-(\d{2})-(\d{2})/;,三个圆括号形成了三个组匹配。 代码: const RE_DATE /(\d{4})-(\d{2})-(\d{2})/;const matchObj RE_DATE.exec(1999-12-31); const year matchO…...
自然语言处理技术:NLP句法解析树与可视化方法
自然语言处理(Natural Language Processing,NLP)句法解析树是一种表示自然语言句子结构的图形化方式。它帮助将句子中的每个词汇和短语按照语法规则连接起来,形成一个树状结构,以便更好地理解句子的语法结构和含义。句法解析树对于理解句子的句法关系、依存关系以及语义角…...
flinksql报错 Cannot determine simple type name “org“
flink版本 1.15 报错内容 2023-08-17 15:46:02 java.lang.RuntimeException: Could not instantiate generated class WatermarkGenerator$0at org.apache.flink.table.runtime.generated.GeneratedClass.newInstance(GeneratedClass.java:74)at org.apache.flink.table.runt…...
e.target.value和 binding.value 区别
e.target.value 和 binding.value 都是在 Vue.js 中用于处理事件绑定时的值,但它们的使用场景和含义有所不同,分别用于普通的 DOM 事件和自定义指令。 e.target.value: 这是常用于原生 DOM 事件处理函数中的一个属性,用于获取事件…...
软链接与exec进程替换运行路径问题
目录 1. 代码(1)启动进程execvp(2)替换的新进程new_proc 2. 验证(1)new_proc与execvp源文件同一目录(2)new_proc与execvp软链接同一目录 3. 总结4. errno.h 用execvp软链接启动进程&…...
【Go】锁相关
文章目录 Mutex锁mutex源码分析LockUnLock mutex两种运行模式mutex normal 正常模式自旋 mutex starvation 饥饿模式 锁的底层实现类型 RWMutexRWMutex 实现其他共享内存线程安全的方式 思考如何设计一个并发更高的锁? Mutex锁 mutex源码分析 Locker接口ÿ…...
git环境超详细配置说明
一,简介 在git工具安装完成之后,需要设置一下常用的配置,如邮箱,缩写,以及git commit模板等等。本文就来详细介绍些各个配置如何操作,供参考。 二,配置步骤 2.1 查看当前git的配置 git conf…...
使用阿里云服务器搭建PostgreSQL主从架构图文流程
阿里云百科分享使用阿里云服务器搭建PostgreSQL主从架构图文流程,PostgreSQL被业界誉为最先进的开源数据库,支持NoSQL数据类型(JSON/XML/hstore)。本文档介绍在CentOS 7操作系统的ECS实例上搭建PostgreSQL主从架构的操作步骤。 目…...
Linux的基本权限(文件,目录)
文章目录 前言一、Linux权限的概念二、Linux权限管理 1.文件访问者分类2.文件类型和访问类型3.文件访问权限的相关设置方法三、目录的权限四、权限的总结 前言 Linux下一切皆文件,指令的本质就是可执行文件,直接安装到了系统的某种路径下 一、Linux权限的…...
网络编程(12): TCP重传、滑动窗口、流量控制、拥塞控制
1、TCP重传机制 通过序列号和确认号确保可靠传输,当发送端发送数据给接收到,接收端会返回一个确认号,表示收到消息了 超时重传:没有在指定时间内收到ACK报文 超时重传的两种可能:数据包丢失、确认包丢失超时重传时间RT…...
Docker安装RabbitMQ服务端
使用docker安装RabbitMQ服务端 1、搜索镜像 docker search rabbitmq2、拉取镜像 默认拉取最后一个版本,可以在后面加版本号拉取指定版本 docker pull rabbitmq 3、运行镜像 docker run -d --hostname my-rabbit --name rabbit -p 15672:15672 rabbitmq4、查看…...
vueuse常用方法
useDateFormat 时间格式化 <script setup lang"ts">import { useNow, useDateFormat } from vueuse/coreconst formatted useDateFormat(useNow(), YYYY-MM-DD HH:mm:ss)</script><template><div>{{ formatted }}</div> </templa…...
选择大型语言模型自定义技术
推荐:使用 NSDT场景编辑器 助你快速搭建可二次编辑器的3D应用场景 企业需要自定义模型来根据其特定用例和领域知识定制语言处理功能。自定义LLM使企业能够在特定的行业或组织环境中更高效,更准确地生成和理解文本。 自定义模型使企业能够创建符合其品牌…...
算法概述-Java常用算法
算法概述-Java常用算法 1、算法概念2、算法相关概念3、算法的性能评价4、算法应用归纳 1、算法概念 广泛算法定义:算法是模型分析的一组可行性的、确定的和有穷的规则。 经典算法特征:有穷性、确切性、输入、输出和可行性。 常用的算法包括递推、递归、穷…...
CCLINK转MODBUS-TCP网关cclink通讯接线图 终端电阻
大家好,今天我们要聊的是生产管理系统中的CCLINK和MODBUS-TCP协议,它们的不同使得数据互通比较困难,但捷米JM-CCLK-TCP网关的出现改变了这一切。 1捷米JM-CCLK-TCP是一款自主研发的CCLINK从站功能的通讯网关,它的主要功能是将各种…...
香蕉派 BPI-P2 Pro采用RK3308芯片,512M内存,8G存储,支持PoE供电
Banana Pi BPI-P2 pro(Armsom pro)是一款基于瑞芯瑞(Rockchip) RK3308B-S芯片的开发板。采用高性能4核ARM Cortex-A35处理器,512M RAM内存。和8G eMMC板载存储,支持PoE网线供电功能。芯片具有丰富的接口,如I2S、PCM、TDM、I2C、UART、SPDIF、…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...
