详解Java的类文件结构(.class文件的结构)

news2024/10/24 22:18:35

 

  • this_class 指向常量池中索引为 2 的 CONSTANT_Class_info。
  • super_class 指向常量池中索引为 3 的 CONSTANT_Class_info。
  • 由于没有接口,所以 interfaces 的信息为空。

对应 class 文件中的位置如下图所示。

 

06、字段表

一个类中定义的字段会被存储在字段表(fields)中,包括静态的和非静态的。

来看这样一段代码。

public class FieldsTest {
    private String name;
}

字段只有一个,修饰符为 private,类型为 String,字段名为 name。可以用下面的伪代码来表示 field 的结构。

field_info {
  u2 access_flag;
  u2 name_index;
  u2 description_index;
}
  • access_flag 为字段的访问标记,比如说是不是 public | private | protected,是不是 static,是不是 final 等。
  • name_index 为字段名的索引,指向常量池中的 CONSTANT_Utf8_info, 比如说上例中的值就为 name。
  • description_index 为字段的描述类型索引,也指向常量池中的 CONSTANT_Utf8_info,针对不同的数据类型,会有不同规则的描述信息。

1)对于基本数据类型来说,使用一个字符来表示,比如说 I 对应的是 int,B 对应的是 byte。

2)对于引用数据类型来说,使用 L***; 的方式来表示,L 开头,; 结束,比如字符串类型为 Ljava/lang/String;

3)对于数组来说,会用一个前置的 [ 来表示,比如说字符串数组为 [Ljava/lang/String;

对应到 class 文件中的位置如下图所示。

 

看到这里相信你就能明白经常在 javap 命令中看到的一些奇怪的字符的意思了。

07、方法表

方法表和字段表类似,区别是用来存储方法的信息,包括方法名,方法的参数,方法的签名。

就拿 main 方法来说吧。

public class MethodsTest {
    public static void main(String[] args) {
        
    }
}

先用 jclasslib 看一下大概的信息。

 

  • 访问标记是 public static 的。
  • 方法名为 main。
  • 方法的参数为字符串数组;返回类型为 Void。

对应到 class 文件中的位置如下图所示。

 

08、属性表

属性表是 class 文件中的最后一部分,通常出现在字段和方法中。

来看这样一段代码。

public class AttributeTest {
    public static final int DEFAULT_SIZE = 128;
}

只有一个常量 DEFAULT_SIZE,它属于字段中的一种,就是加了 final 的静态变量。先通过 jclasslib 看一下它当中一个很重要的属性——ConstantValue,用来表示静态变量的初始值。

 

  • Attribute name index 指向常量池中值为“ConstantValue”的常量。
  • Attribute length 的值为固定的 2,因为索引只占两个字节的大小。
  • Constant value index 指向常量池中具体的常量,如果常量类型为 int,指向的就是 CONSTANT_Integer_info。

我画了一副图,可以完整的表示字段的结构,包含属性表在内。

 

对应到 class 文件中的位置如下图所示。

来看下面这段代码。

public class MethodCode {
    public static void main(String[] args) {
        foo();
    }

    private static void foo() {
    }
}

main 方法中调用了 foo 方法。通过 jclasslib 看一下它当中一个很重要的属性——Code, 方法的关键信息都存储在里面。

 

  • Attribute name index 指向常量池中值为“Code”的常量。
  • Attribute length 为属性值的长度大小。
  • bytecode 存储真正的字节码指令。
  • exception table 表示方法内部的异常信息。
  • maximum stack size 表示操作数栈的最大深度,方法执行的任意期间操作数栈深度都不会超过这个值。
  • maximum local variable 表示临时变量表的大小,注意,并不等于方法中所有临时变量的数量之和,当一个作用域结束,内部的临时变量占用的位置就会被替换掉。
  • code length 表示字节码指令的长度。

对应 class 文件中的位置如下图所示。

 

09、QA

评论区有读者问到:“怎么通过索引值,定位到在class 文件中的位置,这个是咋算的?”

在Java类文件中,常量池是一个索引表,它从索引值1开始计数,每个条目都有一个唯一的索引。

  • 常量池计数器:在常量池之前,类文件有一个16位的常量池计数器,表示常量池中有多少项。它的值比实际常量数大1(因为索引从1开始)。
  • 常量池条目:每个常量池条目的开始是一个标签(1个字节),表明了常量的类型(如Class、Fieldref、Methodref等)。根据这个类型,后面跟着的数据结构也不同。

定位过程大致如下:

  • 读取常量池计数器:首先,从类文件的开头读取常量池计数器的值,确定常量池中有多少条目。
  • 遍历常量池:从常量池的第一项开始遍历。由于不同类型的常量长度不同,需要根据每个常量的类型来确定它的长度。
  • 根据索引定位:继续遍历,直到到达所需的索引值。每次遍历时,根据条目类型读取相应长度的数据,直到达到目标索引。

可以抽象成一个数组和一个 for 循环,就能明白了。

int[] constantPool = new int[constantPoolCount];
for (int i = 1; i < constantPoolCount; i++) {
    int tag = constantPool[i];
    switch (tag) {
        case CONSTANT_Integer_info:
            i += 4;
            break;
        case CONSTANT_Float_info:
            i += 4;
            break;
        case CONSTANT_Long_info:
            i += 8;
            break;
        case CONSTANT_Double_info:
            i += 8;
            break;
        case CONSTANT_Utf8_info:
            int length = constantPool[i + 1];
            i += length + 1;
            break;
        case CONSTANT_String_info:
            i += 2;
            break;
        case CONSTANT_Class_info:
            i += 2;
            break;
        case CONSTANT_Fieldref_info:
            i += 4;
            break;
        case CONSTANT_Methodref_info:
            i += 4;
            break;
        case CONSTANT_InterfaceMethodref_info:
            i += 4;
            break;
        case CONSTANT_NameAndType_info:
            i += 4;
            break;
        case CONSTANT_MethodHandle_info:
            i += 3;
            break;
        case CONSTANT_MethodType_info:
            i += 2;
            break;
        case CONSTANT_InvokeDynamic_info:
            i += 4;
            break;
        default:
            throw new RuntimeException("Unknown tag: " + tag);
    }
}

10、小结

到此为止,class 文件的内部算是剖析得差不多了,希望能对大家有所帮助。第一次拿刀,手有点颤,如果哪里有不足的地方,欢迎大家在评论区毫不留情地指出来!

  • class 文件是一串连续的二进制,由 0 和 1 组成,但我们仍然可以借助一些工具来看清楚它的真面目。
  • class 文件的内容通常可以分为下面这几部分,魔数、版本号、常量池、访问标记、类索引、父类索引、接口索引、字段表、方法表、属性表。
  • 常量池包含了类、接口、字段和方法的符号引用,以及字符串字面量和数值常量。
  • 访问标记用于识别类或接口的访问信息,比如说是不是 public | private | protected,是不是 static,是不是 final 等。
  • 类索引、父类索引和接口索引用来确定类的继承关系。
  • 字段表用来存储字段的信息,包括字段名,字段的参数,字段的签名。
  • 方法表用来存储方法的信息,包括方法名,方法的参数,方法的签名。
  • 属性表用来存储属性的信息,包括字段的初始值,方法的字节码指令等。

相信大家看完这篇内容应该能对 class 文件有一个比较清晰的认识了。

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

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

相关文章

zotero文献管理学习

1 zotero软件简介 zotero是一款开源的文献管理软件。如果你听说或使用过EndNote&#xff0c;那么可能会对“文献管理”有一定的概念。可以简单地这样理解&#xff1a;zotero一定程度上可以作为EndNote的平替。 EndNote需要注册付费&#xff0c;对于无专业科研机构隶属关系的企…

MATLAB运动目标检测系统

应用背景 运动目标的定位跟踪&#xff0c;检测识别&#xff0c;运动分析在图像压缩、运动分析、交通检测&#xff0c;智能监控等方面有主要的应用。 首先&#xff0c;在图像压缩中&#xff0c;运动目标检测技术可以在背景区域中将前景区域提取分割出来&#xff0c;只传递部分…

植物端粒到端粒(T2T)基因组研究进展与展望

鼠鼠跳槽了&#xff0c;因为现在公司发(bu)展(zhang)受(gong)限(zi)&#xff0c;只能跳一次&#xff0c;从大兴到昌平了。从二代ivd行业去三代T2T和泛基因组了。在这里我们分享一篇文章。 摘要&#xff1a;高质量的参考基因组是基因组学研究的基础。目前&#xff0c;大多数的参…

笨蛋学习FreeMarker

笨蛋学习FreeMarker FreeMarker参考网址创建实例引入Maven创建工具类创建实例并进行输出 FreeMarker数据类型布尔型&#xff1a;日期型&#xff1a;数值型&#xff1a;字符型&#xff1a;需要处理字符串为null的情况&#xff0c;否则会报错字符串为空不会报错cap_firstuncap_fi…

【银河麒麟高级服务器操作系统实例】金融行业TCP连接数猛增场景的系统优化

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 服务器环境以及配置 物理机/虚拟机/云/容器 物理…

12 django管理系统 - 注册与登录 - 登录

为了演示方便&#xff0c;我就直接使用models里的Admin来演示&#xff0c;不再创建用户模型了。 ok&#xff0c;先做基础配置 首先是在base.html中&#xff0c;新增登录和注册的入口 <ul class"nav navbar-nav navbar-right"><li><a href"/ac…

使用 VSCode 通过 Remote-SSH 连接远程服务器详细教程

使用 VSCode 通过 Remote-SSH 连接远程服务器详细教程 在日常开发中&#xff0c;许多开发者需要远程连接服务器进行代码编辑和调试。Visual Studio Code&#xff08;VSCode&#xff09;提供了一个非常强大的扩展——Remote-SSH&#xff0c;它允许我们通过 SSH 协议直接连接远程…

一图读懂“低空经济”

&#x1f482; 个人主页: 同学来啦&#x1f91f; 版权: 本文由【同学来啦】原创、在CSDN首发、需要转载请联系博主 &#x1f4ac; 如果文章对你有帮助&#xff0c;欢迎关注、点赞、收藏和订阅专栏哦 文章目录 ✈️ 一、低空经济简介&#x1f534; 1、基本含义&#x1f7e0; 2、…

【免费领取】基于javaweb实现的的日志管理系统

主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 项目描述 本工作日志管理系统是一个面向中小企业的简单的工作管理系统&#xff0c;它主要实现公…

【Python】Pandas基础操作手册(上)

哈喽&#xff0c;哈喽&#xff0c;大家好~ 我是你们的老朋友&#xff1a;保护小周ღ 今天给大家带来的是【Python】Pandas基础操作手册&#xff08;上&#xff09;本次主要讲解, python pandas 模块的一些基本概念, 以及了解 Dataframe 对象的创建, 赋值, 保存. 一起来看看叭…

【SpringBoot】17 多文件上传(Thymeleaf + MySQL)

Git仓库 https://gitee.com/Lin_DH/system 文件上传 可参考上一篇【SpringBoot】16 文件上传&#xff08;Thymeleaf MySQL&#xff09; https://blog.csdn.net/weixin_44088274/article/details/143004298 介绍 文件上传是指将本地的图片、视频、音频等文件上传到服务器&…

php生成PDF文件(FPDF)

FPDF即“Free PDF”&#xff0c;FPDF类库提供了基本的PDF创建功能&#xff0c;其源代码和使用权是免费的。 PDF格式文档优势 通用&#xff1a;PDF文档在UNIX和Windows系统均可正常使用。 安全&#xff1a;PDF文档可设置为只读模式&#xff0c;并且可以添加密码等保护措施。 美…

【PDF文件】默认被某种软件打开,如何进行修改?

当有时下载某种软件后&#xff0c;电脑中的PDF文件就默认由该种软件打开&#xff0c;每次需要右键选择打开方式才能选择需要的其他软件打开。如下图所示。 修改方法&#xff1a; &#xff08;1&#xff09;点击电脑的“设置”&#xff0c;选择应用 &#xff08;2&#xff09;…

深入浅出理解BLE AUDIO CSIS

CSIS是Coordinate Sets Identification service,翻译过来就是协调集识别服务。什么是协调集&#xff0c;可以理解为具有相同特征的一伙设备&#xff0c;最典型的就是左右两个蓝牙耳机是一个协调集&#xff0c;所以它们具有相同的协调集标志&#xff0c;但是具有相同协调集的设备…

disql 全量备份SQL脚本DM7/DM8

disql 全量备份SQL脚本DM7/DM8 环境介绍1 全量备份前准备工作2 全量备份2.1 cd 到数据库bin 目录,并编辑文件2.2 编写数据库全量备份SQL 脚本2.3 执行编写的sql脚本2.4 编写Linux定时任务 , 每月执行全量备份 3 备份还原4 增量备份配置5 更多达梦数据库学习使用列表 环境介绍 …

CTA-GAN:基于生成对抗网络对颈动脉和主动脉的非增强CT影像进行血管增强

写在前面 目前只分析了文章的大体内容和我个人认为的比较重要的细节&#xff0c;代码实现还没仔细看&#xff0c;后续有时间会补充代码细节部分。 文章地址&#xff1a;Generative Adversarial Network-based Noncontrast CT Angiography for Aorta and Carotid Arteries 代…

【C++】STL容器-string常用接口

1.string类的优势及重要性&#xff08;部分&#xff09; C语言中&#xff0c;字符串是以’\0’结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C标准库中提供了一些str系列的库函数&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不太符合OOP的思想&…

【Unity实战笔记】第二一 · 基于状态模式的角色控制——以UnityChan为例

目录 一 内容摘要二 前言三 状态模式的必要性3.1 非状态模式的角色控制3.2 简易状态模式的角色控制3.3 状态模式3.3.1 IState3.3.2 IdleState3.3.3 RunState3.3.4 JumpState3.3.5 PlayerController_ComplexStateMode3.3.6 注意事项 3.4 SMB 四 基于SMB的角色控制4.1 项目实战案…

Java | Leetcode Java题解之第497题非重叠矩形中的随机点

题目&#xff1a; 题解&#xff1a; class Solution {Random rand;List<Integer> arr;int[][] rects;public Solution(int[][] rects) {rand new Random();arr new ArrayList<Integer>();arr.add(0);this.rects rects;for (int[] rect : rects) {int a rect[0…

【大模型问答测试】大模型问答测试脚本实现(第二版)——接入pytest与代码解耦

背景 接上一篇&#xff0c;【大模型问答测试】大模型问答测试脚本实现&#xff08;第一版&#xff09;。 在实现自动化的时候&#xff0c;原先把很多方法与request请求写在一块了&#xff0c;趁着目前实现接口数量较少&#xff0c;决定对代码进行解耦&#xff0c;并且清晰目录…