Java class文件格式之访问标志信息_动力节点Java学院整理
发布时间 - 2026-01-11 01:52:58 点击率:次class文件中的访问标志信息

位于常量池下面的2个字节是access_flags 。 access_flags 描述的是当前类(或者接口)的访问修饰符, 如public, private等, 此外, 这里面还存在一个标志位, 标志当前的额这个class描述的是类, 还是接口。access_flags 的信息比较简单, 下面列出access_flags 中的各个标志位的信息。本来写这个系列博客参考的是《深入java虚拟机》, 但是这本书比较老了, 关于java 5以后的新特性没有进行解释,这本书中指列出了5个标志值, 而最新的JVM规范是针对java 7 的, 其中加入了额外的三个标志位。 分别是ACC_SYNTHETIC, ACC_ANNOTATION 和 ACC_ENUM 。
| 标志名 | 标志值 | 标志含义 | 针对的对像 |
| ACC_PUBLIC | 0x0001 | public类型 | 所有类型 |
| ACC_FINAL | 0x0010 | final类型 | 类 |
| ACC_SUPER | 0x0020 | 使用新的invokespecial语义 | 类和接口 |
| ACC_INTERFACE | 0x0200 | 接口类型 | 接口 |
| ACC_ABSTRACT | 0x0400 | 抽象类型 | 类和接口 |
| ACC_SYNTHETIC | 0x1000 | 该类不由用户代码生成 | 所有类型 |
| ACC_ANNOTATION | 0x2000 | 注解类型 | 注解 |
| ACC_ENUM | 0x4000 | 枚举类型 | 枚举 |
其他标志就不做介绍了, 这些标志都很简单。 读者感觉比较陌生的可能是ACC_SUPER这个标志。 读者会想, 类型不能被super关键字修饰啊, 那这个ACC_SUPER是做什么的呢?表中可以看出, 它的含义是:使用新的invokespecial语义 。 invokespecial是一个字节码指令, 用于调用一个方法, 一般情况下, 调用构造方法或者使用super关键字显示调用父类的方法时, 会使用这条字节码指令。 这正是ACC_SUPER这个名字的由来。 在java 1.2之前, invokespecial对方法的调用都是静态绑定的, 而ACC_SUPER这个标志位在java 1.2的时候加入到class文件中, 它为invokespecial这条指令增加了动态绑定的功能。 这里可能有几个概念读者不是很明白, 如静态绑定, 动态绑定等, 这些概念会在以后的博客中详细介绍。
还有一点需要说明, 既然access_flags 出现在class文件中的类的层面上, 那么它只能描述类型的修饰符, 而不能描述字段或方法的修饰符, 希望读者不要将这里的access_flags 和后面要介绍的方法表和字段表中的访问修饰符相混淆。
此外, 在Java 5 的中, 引入和注解和枚举的新特性, 那么可以推测, ACC_ANNOTATION 和 ACC_ENUM是在Java 5版本中加入的。 class文件虽然总体上保持前后一致性, 但他也不是一成不变的, 也会跟着Java版本的提升而有所改变, 但是总体来说, class文件格式还是相对稳定的, 变动的地方不是很多。
class文件中的this_class
访问标志access_flags 下面的两个字节叫做this_class, 它是对当前类的描述。 它的两个字节的数据是对常量池中的一个CONSTANT_Class_info数据项的一个索引。 CONSTANT_Class_info在上面的文章中已经介绍过了。 CONSTANT_Class_info中有一个字段叫做name_index , 指向一个CONSTANT_Utf8_info , 在这个CONSTANT_Utf8_info 中存放着当前类的全限定名。
如果当前类为Person:
package combjpowernodetest;
public class Person {
int age;
int getAge(){
return age;
}
}
将Person.class反编译后, 可以在常量池中看到如下两项:
Constant pool: #1 = Class #2 // com/bjpowernode/test/Person #2 = Utf8 com/bjpowernode/test/Person ......... .........
这两项就是当前类的信息。 其中索引为1的CONSTANT_Class_info会被class文件中的this_class所引用。 下面给出示例图(其中虚线范围内表示常量池的区域):
class文件中的super_class
super_class紧跟在this_class之后。 它和this_class一样是一个指向常量池数据项的索引。 它指向一个CONSTANT_Class_info, 这个CONSTANT_Class_info数据项描述的是当前类的超类的信息。CONSTANT_Class_info中的name_index指向常量池中的一个CONSTANT_Utf8_info ,CONSTANT_Utf8_info 中存放的是当前类的超类的全限定名。 如果没有显式的继承一个,也就是说如果当前类是直接继承Object的, 那么super_class值为0 。 我们在前面的文章中提到过, 如果一个索引值为0, 那么就说明这个索引不引用任何常量池中的数据项, 因为常量池中的数据项是从1开始的。 也就是说, 如果一个类的class文件中的super_class为0 , 那么就代表该类直接继承Object类。
下面以代码来说明:
package combjpowernodetest;
public class Programer extends Person{
Computer computer;
public Programer(Computer computer){
thiscomputer = computer;
}
public void doWork(){
computercalculate();
}
}
上面的Programer类继承自Person类。 那么反编译Programer .class , 它的常量池中会存在如下信息:
Constant pool: ......... ......... #3 = Class #4 // com/bjpowernode/test/Person #4 = Utf8 com/bjpowernode/test/Person
这两项就是当前类的父类的信息。 其中索引为3的CONSTANT_Class_info会被class文件中的super_class引用。 下面给出示例图(其中虚线范围内表示常量池的区域):
class文件中的interfaces_count和interfaces
紧接着super_class的是interfaces_count, 表示当前类所实现的接口的数量或者当前接口所继承的超接口的数量。 注意, 只有当前类直接实现的接口才会被统计, 如果当前类继承了另一个类, 而另一个类又实现了一个接口, 那么这个接口不会统计在当前类的interfaces_count中。 在interfaces_count后面是interfaces, 他可以看做是一个数组, 其中的每个数组项是一个索引, 指向常量池中的一个CONSTANT_Class_info, 这个CONSTANT_Class_info又会引用常量池中的一个CONSTANT_Utf8_info , 这个CONSTANT_Utf8_info 中存放着有当前类型直接实现或继承的接口的全限定名。 当前类型实现或继承了几个接口, 在interfaces数组中就会有几个数项与之相对应。
下面看代码示例:
package combjpowernodetest;
public class Plane implements IFlyable, Cloneable{
@Override
public void fly() {
}
}
Plane类实现了一个自定义的IFlyable接口, 还实现了一个JDK中的Cloneable接口, 那么它的常量池中会有如下信息:
Constant pool: ......... ......... #5 = Class #6 // com/bjpowernode/test/IFlyable #6 = Utf8 com/bjpowernode/test/IFlyable #7 = Class #8 // java/lang/Cloneable #8 = Utf8 java/lang/Cloneable ......... .........
这四项数据就是当前的Plane类所实现的接口的信息。 第五项和第六项描述了Plane所实现的IFlyable接口, 第七项和第八项描述了Plane所实现的接口Cloneable接口。 下面是示意图(其中虚线范围内表示常量池的区域):
总结
主要讲解了三个部分, 分别是this_class , super_class , interfaces_count和interfaces 。 这三个数据项分别描述了当前类(就是当前class文件所在的类), 当前类所继承的超类, 和当前类所实现的接口(如果当前class文件代表的是一个接口, 那么 interfaces_count和interfaces描述的是当前接口所继承的超接口)。
这几个数据项都持有指向常量池的索引。 真实的信息都是存放在常量池中的, 只不过常量池中的这些信息会被this_class , super_class , interfaces_count和interfaces 引用。
# Java
# class文件访问标志信息
# class
# 访问标志信息
# class文件格式
# Java实现文件上传到服务器本地并通过url访问的方法步骤
# JavaWeb踩坑记录之项目访问不到html文件
# 使用Java7的Files工具类和Path接口来访问文件的方法
# Java编程利用socket多线程访问服务器文件代码示例
# Spring MVC访问静态文件_动力节点Java学院整理
# Java访问Hadoop分布式文件系统HDFS的配置说明
# Java文件拒绝访问问题及解决
# 的是
# 池中
# 是一个
# 绑定
# 都是
# 会有
# 修饰符
# 这条
# 实现了
# 这本书
# 放着
# 值为
# 这两项
# 新特性
# 也就是说
# 反编译
# 几个
# 也不
# 是在
# 放在
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
5种Android数据存储方式汇总
如何用免费手机建站系统零基础打造专业网站?
linux top下的 minerd 木马清除方法
如何撰写建站申请书?关键要点有哪些?
*服务器网站为何频现安全漏洞?
Laravel怎么解决跨域问题_Laravel配置CORS跨域访问
UC浏览器如何设置启动页 UC浏览器启动页设置方法
Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧
高端网站建设与定制开发一站式解决方案 中企动力
个人网站制作流程图片大全,个人网站如何注销?
佛山企业网站制作公司有哪些,沟通100网上服务官网?
韩国服务器如何优化跨境访问实现高效连接?
Laravel如何实现数据导出到PDF_Laravel使用snappy生成网页快照PDF【方案】
iOS中将个别页面强制横屏其他页面竖屏
HTML 中动态设置元素 name 属性的正确语法详解
教学论文网站制作软件有哪些,写论文用什么软件
?
微信公众帐号开发教程之图文消息全攻略
米侠浏览器网页图片不显示怎么办 米侠图片加载修复
如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环
laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析
Windows10怎样连接蓝牙设备_Windows10蓝牙连接步骤【教程】
PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】
如何快速建站并高效导出源代码?
Laravel Fortify是什么,和Jetstream有什么关系
Java垃圾回收器的方法和原理总结
EditPlus中的正则表达式 实战(1)
百度浏览器如何管理插件 百度浏览器插件管理方法
网易LOFTER官网链接 老福特网页版登录地址
Laravel怎么实现微信登录_Laravel Socialite第三方登录集成
Laravel如何使用Collections进行数据处理?(实用方法示例)
如何用5美元大硬盘VPS安全高效搭建个人网站?
javascript基本数据类型及类型检测常用方法小结
如何彻底删除建站之星生成的Banner?
如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)
如何使用 jQuery 正确渲染 Instagram 风格的标签列表
大学网站设计制作软件有哪些,如何将网站制作成自己app?
如何生成腾讯云建站专用兑换码?
Laravel怎么防止CSRF攻击_Laravel CSRF保护中间件原理与实践
Laravel如何自定义错误页面(404, 500)?(代码示例)
成都品牌网站制作公司,成都营业执照年报网上怎么办理?
Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理
手机软键盘弹出时影响布局的解决方法
Android中Textview和图片同行显示(文字超出用省略号,图片自动靠右边)
,网页ppt怎么弄成自己的ppt?
什么是javascript作用域_全局和局部作用域有什么区别?
焦点电影公司作品,电影焦点结局是什么?
Laravel怎么设置路由分组Prefix_Laravel多级路由嵌套与命名空间隔离【步骤】
Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用
厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?
JavaScript中如何操作剪贴板_ClipboardAPI怎么用

