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文件拒绝访问问题及解决
# 的是
# 池中
# 是一个
# 绑定
# 都是
# 会有
# 修饰符
# 这条
# 实现了
# 这本书
# 放着
# 值为
# 这两项
# 新特性
# 也就是说
# 反编译
# 几个
# 也不
# 是在
# 放在
相关文章:
完全自定义免费建站平台:主题模板在线生成一站式服务
建站之星客服服务时间及联系方式如何?
建站之星后台管理:高效配置与模板优化提升用户体验
c++ stringstream用法详解_c++字符串与数字转换利器
如何用虚拟主机快速搭建网站?详细步骤解析
建站之星安全性能如何?防护体系能否抵御黑客入侵?
网站制作公司,橙子建站是合法的吗?
建站之星价格显示格式升级,你的预算足够吗?
七夕网站制作视频,七夕大促活动怎么报名?
IOS倒计时设置UIButton标题title的抖动问题
香港服务器租用费用高吗?如何避免常见误区?
网站规划与制作是什么,电子商务网站系统规划的内容及步骤是什么?
公司网站制作需要多少钱,找人做公司网站需要多少钱?
简单实现Android文件上传
PHP正则匹配日期和时间(时间戳转换)的实例代码
如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?
打鱼网站制作软件,波克捕鱼官方号怎么注册?
建站主机如何选?高性价比方案全解析
XML的“混合内容”是什么 怎么用DTD或XSD定义
大学网站设计制作软件有哪些,如何将网站制作成自己app?
如何配置支付宝与微信支付功能?
无锡制作网站公司有哪些,无锡优八网络科技有限公司介绍?
建站之星导航配置指南:自助建站与SEO优化全解析
制作电商网页,电商供应链怎么做?
如何处理“XML格式不正确”错误 常见XML well-formed问题解决方法
如何通过虚拟机搭建网站?详细步骤解析
Android滚轮选择时间控件使用详解
免费公司网站制作软件,如何申请免费主页空间做自己的网站?
湖州网站制作公司有哪些,浙江中蓝新能源公司官网?
文字头像制作网站推荐软件,醒图能自动配文字吗?
义乌企业网站制作公司,请问义乌比较好的批发小商品的网站是什么?
商务网站制作工程师,从哪几个方面把握电子商务网站主页和页面的特色设计?
如何基于云服务器快速搭建个人网站?
家庭建站与云服务器建站,如何选择更优?
高端云建站费用究竟需要多少预算?
建站主机无法访问?如何排查域名与服务器问题
b2c电商网站制作流程,b2c水平综合的电商平台?
建站之星ASP如何实现CMS高效搭建与安全管理?
建站之星好吗?新手能否轻松上手建站?
网站制作外包价格怎么算,招聘网站上写的“外包”是什么意思?
建站主机CVM配置优化、SEO策略与性能提升指南
建站主机类型有哪些?如何正确选型
香港服务器建站指南:免备案优势与SEO优化技巧全解析
佛山企业网站制作公司有哪些,沟通100网上服务官网?
定制建站策划方案_专业建站与网站建设方案一站式指南
建站主机服务器选型指南与性能优化方案解析
如何通过主机屋免费建站教程十分钟搭建网站?
如何快速建站并高效导出源代码?
专业公司网站制作公司,用什么语言做企业网站比较好?
新网站制作渠道有哪些,跪求一个无线渠道比较强的小说网站,我要发表小说?
*请认真填写需求信息,我们会在24小时内与您取得联系。