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文件拒绝访问问题及解决
# 的是
# 池中
# 是一个
# 绑定
# 都是
# 会有
# 修饰符
# 这条
# 实现了
# 这本书
# 放着
# 值为
# 这两项
# 新特性
# 也就是说
# 反编译
# 几个
# 也不
# 是在
# 放在
相关文章:
如何在阿里云虚拟服务器快速搭建网站?
北京网站制作公司哪家好一点,北京租房网站有哪些?
如何使用Golang安装API文档生成工具_快速生成接口文档
营销式网站制作方案,销售哪个网站招聘效果最好?
车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?
网站制作专业公司有哪些,如何制作一个企业网站,建设网站的基本步骤有哪些?
javascript中的try catch异常捕获机制用法分析
如何有效防御Web建站篡改攻击?
如何自定义建站之星网站的导航菜单样式?
网站制作说明怎么写,简述网页设计的流程并说明原因?
定制建站方案优化指南:企业官网开发与建站费用解析
制作公司内部网站有哪些,内网如何建网站?
如何解决VPS建站LNMP环境配置常见问题?
javascript基本数据类型及类型检测常用方法小结
如何优化Golang Web性能_Golang HTTP服务器性能提升方法
模具网站制作流程,如何找模具客户?
如何用虚拟主机快速搭建网站?详细步骤解析
如何快速重置建站主机并恢复默认配置?
南平网站制作公司,2025年南平市事业单位报名时间?
如何在Golang中使用replace替换模块_指定本地或远程路径
南京网站制作费用,南京远驱官方网站?
免费ppt制作网站,有没有值得推荐的免费PPT网站?
建站主机系统SEO优化与智能配置核心关键词操作指南
如何在搬瓦工VPS快速搭建网站?
小捣蛋自助建站系统:数据分析与安全设置双核驱动网站优化
建站之星多图banner生成与模板自定义指南
焦点电影公司作品,电影焦点结局是什么?
网站制作培训多少钱一个月,网站优化seo培训课程有哪些?
如何选择长沙网站建站模板?H5响应式与品牌定制哪个更优?
零服务器AI建站解决方案:快速部署与云端平台低成本实践
建站之星导航如何优化提升用户体验?
平台云上自助建站如何快速打造专业网站?
建站主机选哪家性价比最高?
学校免费自助建站系统:智能生成+拖拽设计+多端适配
阿里云网站制作公司,阿里云快速搭建网站好用吗?
建站之星会员如何解锁更多建站功能?
如何在阿里云部署织梦网站?
非常酷的网站设计制作软件,酷培ai教育官方网站?
如何在万网ECS上快速搭建专属网站?
c# 在高并发场景下,委托和接口调用的性能对比
网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?
详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)
建站之星如何优化SEO以实现高效排名?
上海制作企业网站有哪些,上海有哪些网站可以让企业免费发布招聘信息?
黑客如何利用漏洞与弱口令入侵网站服务器?
建站之星安装后如何自定义网站颜色与字体?
制作充值网站的软件,做人力招聘为什么要自己交端口钱?
如何通过可视化优化提升建站效果?
建站之星客服服务时间及联系方式如何?
建站之星导航配置指南:自助建站与SEO优化全解析
*请认真填写需求信息,我们会在24小时内与您取得联系。