JVM字节码文件结构深度剖析

反汇编,以下命令可以查看相对可读的详细结构

javap -verbose ByteCode.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];附加属性表
}

在这里插入图片描述

常量池入口,占用二个字节,常量池中的第0个位置被我们的jvm占用了表示为null 所以我们通过编译出来的常量池索引是从1开始的。

常量池是 class 文件中一个用于存放各种**字面量(如字符串、数值)和符号引用(类名、字段、方法名等)**的表。

常量池常量结构表

u1,u2,u4,u8分别代表1个字节,2个字节,4个字节,8个字节的无符号数

tag均是u1

tag常量类型名称结构说明示例
1CONSTANT_Utf8UTF-8 编码字符串u2 length + u1[length] bytes:MUTF-8 编码的字符串“Hello”, “main”, “(I)V”
3CONSTANT_Integer整型常量u4 bytes:32 位整型值100-1
4CONSTANT_Float浮点型常量u4 bytes:IEEE 754 float3.14f
5CONSTANT_Long长整型常量u4 high_bytes + u4 low_bytes(注意占用两项)123456789012345L
6CONSTANT_Double双精度浮点常量u4 high_bytes + u4 low_bytes(注意占用两项)3.1415926535
7CONSTANT_Class类或接口名u2 name_index:指向一个 Utf8 常量java/lang/String
8CONSTANT_String字符串字面量引用u2 string_index:指向一个 Utf8 常量"Hello"
9CONSTANT_Fieldref字段引用u2 class_index + u2 name_and_type_indexSystem.out
10CONSTANT_Methodref方法引用u2 class_index + u2 name_and_type_indexprintln(String)
11CONSTANT_InterfaceMethodref接口方法引用u2 class_index + u2 name_and_type_indexComparable.compareTo(Object)
12CONSTANT_NameAndType名字和类型描述符组合,可以是字段名+类型,也可以是方法名+方法描述符u2 name_index + u2 descriptor_index<init>:()V, add:(II)I

13456属于字面量、其他属于符号引用类型

我们的常量池可以看作我们的java class类的一个资源仓库(比如Java类定的方法和变量信息),我们后面的方法类的信息的描述信息都是通过索引去常量池中获取。

  1. 常量池中主要存放二种常量,一种是字面量 一种是符号引用
    在这里插入图片描述
    在这里插入图片描述

在JVM规范中,每个字段或者变量都有描述信息,描述信息的主要作用是数据类型,方法参数列表,返回值类型等。 基本参数类型和void类型都是用一个大写的字符来表示,对象类型是通过一个大写L加全类名表示,这么做的好处就是在保证jvm能读懂class文件的情况下尽量的压缩class文件体积.

  1. 基本数据类型表示:
  • B---->byte
  • C---->char
  • D---->double
  • F----->float
  • I------>int
  • J------>long
  • S------>short
  • Z------>boolean
  • V------->void
  1. 对象类型:
  • String------>Ljava/lang/String;(前面有个L后面有一个分号)
  1. 对于数组类型: 每一个唯独都是用一个前置[来表示比如:
  • int[] ------>[I
  • String [][]------>[[Ljava.lang.String;

用描述符来描述方法的,先参数列表,后返回值的格式,参数列表按照严格的顺序放在()中
比如String getUserInfoByIdAndName(int id,String name) 的方法描述符号

  • (I,Ljava/lang/String;)Ljava/lang/String;

Class文件结构类的访问标识符号解析 Access_flag

标志位(hex)标志名含义
0x0001ACC_PUBLIC类是 public
0x0010ACC_FINAL类是 final(不可继承)
0x0020ACC_SUPER使用了新的 invokespecial 语义(Java 1.0.2+)
0x0200ACC_INTERFACE是接口
0x0400ACC_ABSTRACT是抽象类
0x1000ACC_SYNTHETIC编译器生成的类
0x2000ACC_ANNOTATION是注解(Annotation)
0x4000ACC_ENUM是枚举类

jvm规范并没有穷举出所以的类型 而是通过位运算的出来的。
0x0021 = 0x0020 位运算 0x0001 那么我们可以得出这个class的访问权限是ACC_PUBLIC 和ACC_SUPER

This class name的描述当前的所属类

this class name 占用二个字节,表示索引

super class name (当前class的父类名字)

同样占用二个字节,也是表示索引值

接口信息

实现的接口数量

占用二个字节表示实现了几个接口,是实现接口数量的上限也是0xffff

实现的接口

每个接口名占两个字节,来表示接口的位于常量池中的索引

字段表信息分析

字段结构

field_info {u2 access_flags;         // 访问标志(如 public、static、final 等)u2 name_index;           // 字段名称(指向常量池的 Utf8 项)u2 descriptor_index;     // 字段类型描述符(指向常量池的 Utf8 项)u2 attributes_count;     // 属性数量attribute_info attributes[attributes_count]; // 属性表(如 ConstantValue 等)
}

field_info.attributes一般会存:

  • ConstantValue
    只有 static final 常量字段才有,存储该字段的常量值(比如 public static final int MAX = 100;),内容是一个指向常量池中具体常量的索引。
  • Deprecated
    标记字段已经废弃,提示编译器或工具警告。
  • Synthetic
    标记字段是编译器生成的,不是源代码写的。
  • RuntimeVisibleAnnotationsRuntimeInvisibleAnnotations
    存储字段上的注解信息。

字段访问标志

标志位(hex)标志名含义
0x0001ACC_PUBLIC字段是 public
0x0002ACC_PRIVATE字段是 private
0x0004ACC_PROTECTED字段是 protected
0x0008ACC_STATIC字段是 static
0x0010ACC_FINAL字段是 final
0x0040ACC_VOLATILE字段是 volatile
0x0080ACC_TRANSIENT字段是 transient
0x1000ACC_SYNTHETIC编译器生成的字段
0x4000ACC_ENUM枚举类型字段

方法表信息分析

方法结构

method_info {u2 access_flags;           // 访问标志(public、static、final等)u2 name_index;             // 方法名索引(指向常量池)u2 descriptor_index;       // 方法描述符索引(参数类型和返回值)(()V 表示的是无参无返)u2 attributes_count;       // 属性个数attribute_info attributes[attributes_count]; // 属性数组(如Code属性)
}

method_info.attributes一般会存:

属性名说明
Code最核心: 存放方法的字节码指令、栈帧信息等(非 abstract/native 方法必须有)
Exceptions声明该方法可能抛出的异常列表(即 throws
LineNumberTable源代码行号到字节码地址的映射(调试用)
LocalVariableTable局部变量名、类型、作用域(调试用)
RuntimeVisibleAnnotations运行时可见注解
RuntimeInvisibleAnnotations编译期注解,运行时不可见
Synthetic标记该方法是编译器生成的,不是源代码写的
Deprecated标记该方法已过时
Signature泛型信息描述(如果用了泛型)
MethodParameters记录参数名(从Java 8开始)

方法访问标志

标志位(hex)标志名含义
0x0001ACC_PUBLIC方法是 public
0x0002ACC_PRIVATE方法是 private
0x0004ACC_PROTECTED方法是 protected
0x0008ACC_STATIC方法是 static
0x0010ACC_FINAL方法是 final
0x0020ACC_SYNCHRONIZED方法是 synchronized
0x0040ACC_BRIDGE编译器生成的桥接方法
0x0080ACC_VARARGS方法使用可变参数
0x0100ACC_NATIVE方法是本地方法(native)
0x0400ACC_ABSTRACT抽象方法
0x0800ACC_STRICT使用严格浮点数计算
0x1000ACC_SYNTHETIC编译器生成的方法

attribute_info

attribute_info {u2 attribute_name_index;//attribute名称常量池索引u4 attribute_length;//info长度u1 info[attribute_length];//具体数据
}
  • 类级别属性(ClassFile 末尾的 attributes[])
    • SourceFile_index
              SourceFile_attribute {u2 attribute_name_index;   // 常量池中 "SourceFile" 字符串的索引u4 attribute_length;       // 属性长度,固定为2u2 sourcefile_index;       // 指向常量池中一个 Utf8 字符串,表示源文件名(如 "Test.java")}
      
  • 字段级别属性(field_info 中的 attributes[])
    • ConstantValue
      用于修饰 静态字段(static final),表示该字段的编译时常量值,比如基本类型的字面量(int、long、float、double、String)。JVM 加载类时,会将这个值赋给对应的静态变量。
          ConstantValue_attribute {u2 attribute_name_index;    // 指向常量池中 "ConstantValue" 的 Utf8u4 attribute_length;        // 固定为 2u2 constantvalue_index;     // 指向常量池中该字段的常量值(Integer、Float、Long、Double、String)}
      
  • 方法级别属性(method_info 中的 attributes[])
    • code

      Code_attribute {u2 attribute_name_index;     // 必然指向 "Code"u4 attribute_length;         // 属性总长度(不含前6字节)u2 max_stack;                // 操作数栈最大深度u2 max_locals;              // 局部变量槽个数u4 code_length;              // 字节码长度(表示这个code[] 数组的字节数)u1 code[code_length];        // 字节码指令序列u2 exception_table_length;   // 异常处理表长度{u2 start_pc;u2 end_pc;u2 handler_pc;u2 catch_type; // 指向常量池(异常类),0代表 catch all} exception_table[exception_table_length];u2 attributes_count;//属性表的个数attribute_info attributes[attributes_count]; // Code 的子属性,比如 LineNumberTable 等
      }
      

      code[length]中存的是字节码指令助记符号(JVM执行的机器码)

    • LineNumberTable
      主要作用是 记录字节码指令与源代码行号的对应关系。便调试器定位当前执行的代码行,实现断点、单步调试等功能。

          LineNumberTable_attribute {u2 attribute_name_index;       // 常量池中 "LineNumberTable" 的索引u4 attribute_length;           // 属性长度u2 line_number_table_length;   // 表项个数(有些人对这个属性名定义不同,但是是同一个东西){u2 start_pc;               // 字节码偏移量(指令起始位置)u2 line_number;            // 源代码行号} line_number_table[line_number_table_length];}
      

      line_number_table_length+line_number_table[line_number_table_length]=info[attribute_length]

    • LocalVariableTable

          LocalVariableTable_attribute {u2 attribute_name_index;       // 常量池中 "LocalVariableTable" 字符串的索引u4 attribute_length;           // 属性长度u2 local_variable_table_length; // 局部变量表项数{u2 start_pc;               // 变量作用域开始的字节码偏移(相当于哪个字节码指令开始可以使用这个变量)u2 length;                 // 作用域长度(字节码偏移范围)u2 name_index;             // 变量名,指向常量池Utf8u2 descriptor_index;       // 变量类型描述符,指向常量池Utf8u2 index;                  // 局部变量表槽号} local_variable_table[local_variable_table_length];}
      

      local_variable_table_length+local_variable_table[local_variable_table_length]=info[attribute_length]

    • MethodParameters
      编译器(JDK 8+)如果开启 -parameters 参数,会在字节码里生成这个属性,保留方法参数名。反射时调用 Method.getParameters() 可以获得真实的参数名。

          MethodParameters_attribute {u2 attribute_name_index;u4 attribute_length;u1 parameters_count;{u2 name_index;     // 参数名(常量池Utf8索引)u2 access_flags;   // 参数修饰符,如 final, synthetic, mandated} parameters[parameters_count];}
      

      parameters_count+parameters[parameters_count=info[attribute_length]

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

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

相关文章

跟着chrome面板优化页面性能

没有优化前&#xff1a; 1.对文本进行压缩&#xff1a; 重新打包 运行 评分好像还是没有发生改变&#xff0c;于是我去找别的压缩的途径&#xff0c; npm install --save-dev vite-plugin-compression 然后修改vite.config.js文件 导入compression插件 文件夹中也成功出现了…

网上花店微信小程序完整项目

概述 一款功能完善的网上花店微信小程序完整项目。该项目包含了完整的前后端代码&#xff0c;是一款基于Java技术栈开发的电商类小程序&#xff0c;适合初学者学习的小程序源码。 主要内容 该花店小程序源码采用主流技术架构开发&#xff0c;主要功能模块包括&#xff1a; …

Elasticsearch 搜索的流程

Elasticsearch 的搜索流程是一个分布式协作过程&#xff0c;主要包含 ‌查询阶段&#xff08;Query Phase&#xff09;‌ 和 ‌取回阶段&#xff08;Fetch Phase&#xff09;‌&#xff0c;默认采用 QUERY_THEN_FETCH 模式。以下是详细流程&#xff1a; 一、请求分发与路由 ‌…

用户行为分析:从概念到实践的全面指南

在数字化转型浪潮中&#xff0c;用户行为分析已成为企业决策的核心驱动力。 用户行为分析本质上是对用户与产品交互过程中产生的各类行为数据进行系统性收集、处理和分析&#xff0c;从而揭示用户偏好、预测行为趋势并指导业务决策的过程。它包含三层核心要素&#xff1a;行为…

Claude Code - 终端智能编码助手

文章目录 一、关于 Claude Code1、项目概览2、相关链接资源 二、安装配置三、使用指南1、快速开始2、问题反馈 四、隐私与数据1、数据收集2、隐私保护 一、关于 Claude Code 1、项目概览 Claude Code 是一款终端智能编码工具&#xff0c;能够理解代码库并通过自然语言命令执行…

如何在FastAPI中玩转跨服务权限校验的魔法?

title: 如何在FastAPI中玩转跨服务权限校验的魔法? date: 2025/06/24 08:23:40 updated: 2025/06/24 08:23:40 author: cmdragon excerpt: FastAPI跨服务权限校验通过可信令牌颁发、令牌传播机制和分布式验证实现微服务架构安全。核心组件包括令牌生成服务和验证逻辑,使用…

用 Python 打造立体数据世界:3D 堆叠条形图绘制全解析

在数据可视化的工具箱里&#xff0c;3D 图表总能带来眼前一亮的效果 —— 它突破了二维平面的限制&#xff0c;用立体空间展示多维度数据关系&#xff0c;让复杂的数据层级一目了然。今天我们要解锁的「3D 堆叠条形图」&#xff0c;就是一种能同时呈现类别、子类别、数值大小的…

互联网大厂Java求职面试:AI与大模型技术下的RAG系统架构设计与性能优化

【互联网大厂Java求职面试&#xff1a;AI与大模型技术下的RAG系统架构设计与性能优化】 文章内容 面试官开场白 技术总监&#xff08;李明&#xff09;&#xff1a; “郑薪苦&#xff0c;欢迎来到今天的面试。我是李明&#xff0c;负责我们公司的AI平台架构设计。今天我们将围…

kotlin, BigDecimal可以直接使用大于号>、小于号<进行直接比较大小吗

kotlin&#xff0c; BigDecimal可以直接使用大于号>、小于号<进行直接比较大小吗&#xff0c;比如 if (BigDecimal(count) < BigDecimal(100) &#xff09; deepseek回答&#xff1a; 我们正在讨论Kotlin中的BigDecimal比较操作。 用户的问题&#xff1a;是否可以直接…

Harmony状态管理AppStorageV2和PersistenceV2

深入理解ArkUI中的AppStorageV2与PersistenceV2装饰器 引言 在ArkUI应用开发中&#xff0c;状态管理是构建复杂应用的关键环节。随着ArkUI状态管理V2版本的推出&#xff0c;AppStorageV2和PersistenceV2装饰器为开发者提供了更强大、更灵活的状态管理能力。本文将详细介绍这两…

LayUI的table实现行上传图片+mvc

一、layUIJQuery using AMes.Domain.Entity.SystemManage; {Layout null; }<!DOCTYPE html><html> <head><meta name"viewport" content"widthdevice-width" /><title>不合格品处置申请</title><link href"…

ALINX 国产化 FPGA SoM 核心板选型指南:紫光同创 Kosmo2/Titan2/ Logos2/Logos 深度解析

作为紫光同创官方合作伙伴&#xff0c;ALINX 近日发布基于 Kosmo-2 系列新品 PG2K100 核心板 K100。 35mm42mm 的精小尺寸中集成双核 A53 处理器85K FPGA 逻辑单元&#xff0c;1GB DDR3 保障实时数据处理能力&#xff0c;120 pin 工业连接器直插各类设备底板&#xff0c;为空间…

从零到一构建一个现代“C++游戏自研引擎”开发蓝图

当然不可能是真从零到一了&#xff0c;做为一个标题党&#xff0c;标题不牛对不起自己&#xff0c;因为游戏引擎涉及太多领域了&#xff0c;比如图形渲染、物理模拟、音频处理、网络通信等等。每个领域都有专业的解决方案&#xff0c;自己从头实现不仅效率低&#xff0c;而且质…

XSS-labs靶场实战

本文主要对XSS-labs靶场进行介绍&#xff0c;给出了我一步步怎么发现漏洞的过程。 目录 第一关 第二关 第三关 第四关 第五关 第六关 第七关 第八关 第九关 第十关 第十一关 第十二关 第十三关 第十四关 第十五关 第十六关 第一关 没啥好说的&#xff0c;直接…

day46-硬件学习之 小练习及中断

一、蜂鸣器学习 代码实现&#xff1a; 二、BSP工程管理 利用BSP工程管理&#xff0c;使文档显示不杂乱&#xff1b; 将这些文件分为4类&#xff0c;并保存到4个不同的文件夹里。 首先在新的工程文件夹里创建一个之后我们编写的类似led驱动&#xff0c;clk驱动等等外设驱动程序都…

ArkUI-X通过Stage模型开发Android端应用指南(二)

StageApplication初始化支持以下三种方式 1. 通过继承StageApplication的方式进行初始化 import ohos.stage.ability.adapter.StageApplication;public class HiStageApplication extends StageApplication {Overridepublic void onCreate() {super.onCreate();} }2. 继承And…

主从复制的优势是什么?如好搭建一个主从复制呢?

引言&#xff1a; 最近因为时间缘故&#xff0c;学校&#xff0c;比赛&#xff0c;面试很久没有更新了&#xff0c;现在开始将会持续更新&#xff01;&#xff01;&#xff01;欧克。我们往下看&#xff1a; 概述&#xff1a; 主从复制是指将主数据库的DDL和DML操作通过二进制…

Linux Shell脚本中basename和dirname的详细用法教程

在Linux Shell脚本中&#xff0c;basename和 dirname是两个非常实用的命令&#xff0c;常用于处理文件路径和名称。本文将详细介绍这两个命令的用法&#xff0c;并提供丰富的示例代码&#xff0c;以帮助您更好地理解和应用它们。 一、basename命令 1.1 基本用法 basename命令…

3D世界里的“盗梦空间”!在方块里再造一个世界?高级特效get✅

有没有想过&#xff0c;游戏里的镜子、传送门、或者屏幕上播放的实时3D动画是怎么实现的&#xff1f; 答案就是一项黑科技——渲染目标&#xff08;Render Targets&#xff09;。它允许我们不直接渲染到屏幕&#xff0c;而是“偷偷地”渲染到一张幕后的贴图上&#xff0c;然后…

浅析一种基于深度学习算法的维吾尔文OCR技术的实现原理及其应用场景

维吾尔文OCR技术是一种基于人工智能和深度学习技术的维吾尔文光学字符识别工具&#xff0c;能够快速、准确地将印刷体或手写体维吾尔文转换为可编辑、可搜索的数字化文本。该技术适用于政府、教育、出版、金融等多个行业&#xff0c;助力维吾尔文信息的高效处理与智能化管理。 …