Java class文件格式之方法_动力节点Java学院整理

发布时间 - 2026-01-11 01:53:01    点击率:

class文件中的fields_count和fields

fields_count描述的是当前的类中定义的字段的个数,注意,这里包括静态字段, 但不包括从父类继承的字段。如果当前class文件是由一个接口生成的, 那么这里的fields_count描述的是接口中定义的字段, 我们知道,接口中定义的字段默认都是静态的。此外要说明的是,编译器可能会自动生成字段,也就是说, class文件中的字段的数量可能多于源文件中定义的字段的数量。举例来说,编译器会为内部类增加一个字段, 这个字段是指向外围类的对象的引用。

位于fields_count下面的数据叫做fields, 可以把它看做一个数组, 数组中的每一项是一个field_info 。这个数组中一共有fields_count个field_info , 每个field_info都是对一个字段的描述。 下面我们详细讲解field_info的结构。 每个field_info的结构如下:

(1)access_flags

其中access_flags占两个字节, 描述的是字段的访问标志信息。 这里就不在详细介绍了, 下面给出一张表格(该表格来自《深入Java虚拟机》):

(2)name_index

access_flags下面的两个字节是name_index, 这是一个指向常量池的索引, 它描述的是当前字段的字段名。 这个索引指向常量池中的一个CONSTANT_Utf8_info数据项。 这个CONSTANT_Utf8_info数据项中存放的字符串就是当前字段的字段名。 

(3)descriptor_index

name_index下面的两个字节叫做descriptor_index , 它同样是一个指向常量池的索引, 它描述的是当前字段的描述符。 这个索引指向常量池中的一个CONSTANT_Utf8_info数据项。 这个CONSTANT_Utf8_info数据项中存放的字符串就是当前字段的描述符。

(4)attributes_count和attributes

descriptor_index 下面是attributes_count和attributes 。 这是对当前字段所具有的属性的描述。 这里的属性和源文件中的属性不是同一个概念, 在源文件测层面中, 属性是字段的另一种叫法, 希望读者不要疑惑。读者也不要轻视class文件中的属性, 这些属性可以描述很多的信息。 我们会在后面的文章中进行介绍。

attributes_count表示这个字段有几个属性。attributes 可以看成一个数组, 数组中的每一项都是一个attribute_info,每个attribute_info 表示一个属性, 数组中一共有attributes_count个属性。可以出现在filed_info中的属性有三种,分别是ConstantValue, Deprecated, 和 Synthetic。 这些属性会在后面的文章中进行介绍。

下面我们以代码的形式进行解释,源码如下:

package com.bjpowernode.test; 

public class Programer extends Person{ 
 
 private Computer computer; 
 
 public Programer(Computer computer){ 
  this.computer = computer; 
 } 
 
public void doWork(){ 
  computer.calculate(); 
 } 
}

反编译之后, 常量池中会有如下信息(这里省略了大部分无关信息):

Constant pool: 
 
......... 
......... 
 
 #5 = Utf8    computer 
 #6 = Utf8    Lcom/jg/zhang/Computer; 
 
......... 
......... 
 
{ 
 
 private com.jg.zhang.Computer computer; 
 flags: ACC_PRIVATE 
 
......... 
......... 
 
} 

从反编译的结果可以看出,源文件中定义了一个Computer类型的字段computer,并且是private的。然后常量池中有这个字段的字段名和描述符。 其中常量池第五项的CONSTANT_Utf8_info是字段名,第六项的CONSTANT_Utf8_info是该字段的描述符。这里有一点需要说明,在反编译Programer.class时,由于computer是私有的, 要加- private选项,否则的话,虽然常量池中有字段引用信息, 但是不会输出字段信息, 即下面这两行不会输出:

private com.bjpowernode.test.Computer computer; 
flags: ACC_PRIVATE 

如果在javap中加入 - private选项, 那么就会有上面两行的输出。 使用的命令如下:

javap -c -v -private -
classpath . com.bjpowernode.test.Programer 

 根据反编译的结果,可以下面给出示意图, 该图说明了与computer相对应的field_info是不合引用常量池的 ( 其中虚线范围内表示常量池):

class文件中的methods_count和methods

fields下面的信息是methods_count和methods 。 methods_count描述的是当前的类中定义的方法的个数, 注意, 这里包括静态方法, 但不包括从父类继承的方法。 如果当前class文件是由一个接口生成的, 那么这里的methods_count描述的是接口中定义的抽象方法的数量, 我们知道, 接口中定义的方法默认都是公有的。此外需要说明的是, 编译器可能会在编译时向class文件增加额外的方法, 也就是说, class文件中的方法的数量可能多于源文件中由用户定义的方法。 举例来说: 如果当前类没有定义构造方法, 那么编译器会增加一个无参数的构造函数<init>; 如果当前类或接口中定义了静态变量, 并且使用初始化表达式为其赋值, 或者定义了static静态代码块, 那么编译器在编译的时候会默认增加一个静态初始化方法<clinit>。

位于methods_count下面的数据叫做methods,可以把它看做一个数组, 数组中的每一项是一个method_info。这个数组中一共有methods_count个method_info,每个method_info 都是对一个方法的描述。 下面我们详细讲解method_info的结构。每个method_info 的结构如下,几乎和field_info的结构是一样的:

(1)access_flags

 其中access_flags占两个字节, 描述的是方法的访问标志信息。 这里就不在详细介绍了, 下面给出一张表格(该表格来自《深入Java虚拟机》):

(2)name_index

access_flags下面的两个字节是name_index, 这是一个指向常量池的索引, 它描述的是当前方法的方法名。 这个索引指向常量池中的一个CONSTANT_Utf8_info数据项。 这个CONSTANT_Utf8_info数据项中存放的字符串就是当前方法的方法名。

(3)descriptor_index

name_index下面的两个字节叫做descriptor_index , 它同样是一个指向常量池的索引, 它描述的是当前方法的描述符。 这个索引指向常量池中的一个CONSTANT_Utf8_info数据项。 这个CONSTANT_Utf8_info数据项中存放的字符串就是当前方法的描述符。

(4)attributes_count和attributes

descriptor_index 下面是attributes_count和attributes 。 这是对当前方法所具有的属性的描述。 这里的属性和源文件中的属性不是同一个概念, 在源文件测层面中, 属性是字段的另一种叫法, 希望读者不要疑惑。读者也不要轻视class文件中的属性, 这些属性可以描述很多的信息。 我们会在后面的文章中进行介绍。

attributes_count表示这个字段有几个属性。attributes 可以看成一个数组, 数组中的每一项都是一个attribute_info , 每个attribute_info 表示一个属性, 数组中一共有attributes_count个属性。可以出现在method_info 中的属性有三种, 分别是Code, Deprecated, Exceptions 和Synthetic。 在这几个属性中,尤其是Code和Exceptions 非常重要, 这两个属性对于在class文件中完整描述一个方法起着至关重要的作用,其中Code属性中存放方法的字节面指令,Exceptions 属性是对方法声明中抛出的异常的描述。这两属性以及其他一些属性,会在下一篇文章中详细介绍,敬请关注。

介绍完了每个method_info的结构, 下面我们以代码来说明, 还是使用上面的源码:

package com.jg.zhang; 
 
public class Programer extends Person{ 
 
  
 private Computer computer; 
  
 public Programer(Computer computer){ 
  this.computer = computer; 
 } 
  
 public void doWork(){ 
  computer.calculate(); 
 } 
} 

反编译之后, 常量池中会有如下信息(这里省略了大部分无关信息):

Constant pool: 
 
......... 
 
 #7 = Utf8    <init> 
 #8 = Utf8    (Lcom/jg/zhang/Computer;)V 
 
......... 
 
 #12 = Utf8    ()V 
 
......... 
 
 #19 = Utf8    doWork 
 
{ 
 
......... 
 
 public com.jg.zhang.Programer(com.jg.zhang.Computer); 
 flags: ACC_PUBLIC 
 
......... 
 
 public void doWork(); 
 flags: ACC_PUBLIC 
 
......... 
} 

由反编译结果可以看出, 该类中定义了两个方法, 其中一个是构造方法, 一个是doWork方法, 且这两个方法都是public的。 这两个方法的描述信息都存放在常量池。 其中第7项的CONSTANT_Utf8_info为构造方法的方法名, 第8项的CONSTANT_Utf8_info为构造方法的方法描述符, 第19项的CONSTANT_Utf8_info为doWork方法的方法名, 第12项的CONSTANT_Utf8_info为doWork方法的方法描述符。 

根据常量池中的信息, 可以得出如下的示意图, 该示意图形象的说明了class文件中的method_info是如何引用常量池中的数据项来描述当前类中定义的方法的。 图中虚线范围内表示常量池所在的区域:

总结

到此为止, 我们就介绍完了class文件中的fields和methods, 进行一下总结。 
 fields是对当前类中定义的字段的描述, 其中每个字段使用一个field_info表示, fields中有fields_count个field_info。
methods是对当前类或者接口中声明的方法的描述, 其中每个方法使用一个method_info表示, methods中有methods_count个method_info。 

在下一篇博客中,将会介绍class文件中的各个属性,敬请关注。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Java  # class  # 文件格式  # 浅谈JVM之java class文件的密码本  # Java class文件格式之数据类型(二)_动力节点Java学院整理  # Java class文件格式之属性_动力节点Java学院整理  # Java class文件格式之常量池_动力节点Java学院整理  # Java class文件格式之访问标志信息_动力节点Java学院整理  # java虚拟机原理:Class字节码二进制文件分析  # 的是  # 都是  # 池中  # 组中  # 是一个  # 会在  # 反编译  # 类中  # 这两个  # 每一项  # 详细介绍  # 这是  # 字段名  # 会有  # 是由  # 出现在  # 中有  # 举例来说  # 把它  # 这是一个 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何用已有域名快速搭建网站?  Laravel如何配置和使用队列处理异步任务_Laravel队列驱动与任务分发实例  如何在 Telegram Web View(iOS)中防止键盘遮挡底部输入框  如何快速搭建高效可靠的建站解决方案?  HTML5建模怎么导出为FBX格式_FBX格式兼容性及导出步骤【指南】  怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?  EditPlus中的正则表达式 实战(2)  uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址  Laravel如何使用Eloquent ORM进行数据库操作?(CRUD示例)  如何用美橙互联一键搭建多站合一网站?  郑州企业网站制作公司,郑州招聘网站有哪些?  java ZXing生成二维码及条码实例分享  Windows10如何删除恢复分区_Win10 Diskpart命令强制删除分区  网易LOFTER官网链接 老福特网页版登录地址  如何在 React 中条件性地遍历数组并渲染元素  详解vue.js组件化开发实践  Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】  网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?  Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤  免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?  Laravel如何实现全文搜索_Laravel Scout集成Algolia或Meilisearch教程  如何制作一个表白网站视频,关于勇敢表白的小标题?  ,南京靠谱的征婚网站?  如何用虚拟主机快速搭建网站?详细步骤解析  如何基于PHP生成高效IDC网络公司建站源码?  Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)  微信小程序 闭包写法详细介绍  JavaScript如何实现继承_有哪些常用方法  详解jQuery中的事件  长沙做网站要多少钱,长沙国安网络怎么样?  消息称 OpenAI 正研发的神秘硬件设备或为智能笔,富士康代工  利用python获取某年中每个月的第一天和最后一天  Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南  浅述节点的创建及常见功能的实现  googleplay官方入口在哪里_Google Play官方商店快速入口指南  为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】  html如何与html链接_实现多个HTML页面互相链接【互相】  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  Laravel N+1查询问题如何解决_Eloquent预加载(Eager Loading)优化数据库查询  Linux系统命令中tree命令详解  nginx修改上传文件大小限制的方法  Laravel如何配置Horizon来管理队列?(安装和使用)  西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?  Laravel Blade组件怎么用_Laravel可复用视图组件的创建与使用  Laravel如何发送系统通知_Laravel Notifications实现多渠道消息通知  历史网站制作软件,华为如何找回被删除的网站?  Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】  Microsoft Edge如何解决网页加载问题 Edge浏览器加载问题修复  Laravel如何使用Spatie Media Library_Laravel图片上传管理与缩略图生成【步骤】  Laravel怎么定时执行任务_Laravel任务调度器Schedule配置与Cron设置【教程】