当前位置: 首页 > news >正文

java虚拟机学习笔记——java class文件的内容(第六章)

一、class文件内容

注:每个java类只能有一个class文件或接口,下面讨论中u4表示4个字节,u2表示2个字节

class文件内容如下:

  1. magic(魔数)-u4(u4表示4个字节)
    • 0xCAFEBABE,其作用在于可以轻松辨别出Java class文件和非Java class文件;
  2. minor_version-u2和major_version-u2(次、主版本号)
    • 对于虚拟机来说,主次版本号确定了特定的class文件格式,通常只有给定主版本号和一系列次版本号后,虚拟机才能读取该class文件;
    • 如下图所示

      第5、6字节表示次版本号=0
      第7、8字节表示主版本号=50(高位在前)
  3. constant_pool_count-u2和constant_pool(常量池)
    • 常量池的数量为constant_pool_count-1,其索引从1开始;
    • 除直接常量外,常量池还包括类和接口的全限定名、字段的名称和描述符以及方法的名称和描述符等符号引用;
    • 每个常量池入口都有一个字节的标志,这个标志指出了列表中该位置的常量类型。虚拟机获取这个标志后,就知道在标志后面的常量类型了;其中每一个标志都有一个相对应的表结构来描述该常量池;具体类型如下表所示:

  4. access_flags(访问标志)-u2
    • 访问标志展示了文件中类或接口的如下信息:
      标志名设置后的含义
      ACC_PUBLIC0x0001public类型
      ACC_FINAL0x0010类为final类型
      ACC_SUPER0x0020使用新型的invokespecial语义
      ACC_INTERFACE0x0200接口类型,不是类类型
      ACC_ABSTRACT0x0400abstract类型

      附:invokespecial和invokevirtual
      invokespecial指静态绑定后,由JVM产生调用的方法。如super(),以及super.someMethod(),都属于invokespecial;
      invokevirtual指动态绑定后,由JVM产生调用的方法。如obj.someMethod(),属于invokevirtual;
      正是由于这两种绑定的不同,在子类覆盖超类的方法、并向上转型引用后,才产生了多态以及其他特殊的调用结果。

  5. this_class-u2(当前类)
    • 它是一个对常量池的索引,在this_class位置的常量池入口必须为CONSTANT_Class类型对应的表结构CONSTANT_Class_info...;
    • 下图显示了常量池的使用方法:

      在CONSTANT_Utf8_info表的bytes里存放的即是当前类的全限定名字符串;
  6. super_class-u2(直接超类)
    • 和this_class表示的内容相同;
    • 除了java.lang.Object类以外,常量池索引super_class对于所有类均有效;
    • 对于java.lang.Object,其super_class为0;
    • 对于接口,其super_class指向的常量池为java.lang.Object;
  7. interfaces_count-u2和interfaces(接口列表)
    • 保存该类直接实现或该接口所扩展的接口数量;
    • 接口按implements子句和extends子句出现的顺序显现;
    • interfaces表中的每一项都是对父接口的常量池的索引,该索引用CONSTANT_Class_info来描述;
    • 如果接口数为0,则没有interfaces表;
  8. fields_count-u2和fields(字段列表)
    • 只有在class文件中由类或接口声明了的字段才在fields列表中列出,不列出从超类或父接口中继承而来的字段;
    • fields列表可能会包含在对应的Java源文件中没有叙述的字段,这是因为Java编译器可能会在编译时向类或者接口添加字段;如对一个内部类的fields列表来说,为了保持对外围类实例的引用,Java编译器会为每个外围类实例添加实例变量
    • 第个field_info表包含以下字段信息:
      • 字段名字
      • 字段描述符和修饰符
      • 如果该字段被声明为final,则还包含其常量值;
  9. methods_count-u2和methods(方法列表)
    • methods_count表示该类或接口中所声明的所有方法的总计数,不包括超类或都父接口中继承来的方法;
    • methods列表中包含以下信息:
      • 方法名和描述符(方法的返回值类型和参数类型)
      • 如果方法即不是抽象的,也不是本地的,则还包含方法局部变量所需的栈空间长度、为方法所捕获的异常表、字节码序列以及可选的行数和局部变量表
      • 如果方法能够抛出任何已验证异常,则methods列表就会包括一个关于这些已验证异常的列表
  10. attributes_count-u2和attributes(属性列表)
    • class文件中最后的部分是属性,它给出了该文件中类或接口所定义的属性的基本信息;
    • 每个attribute_info表的第一项是指向常量池中CONSTANT_Utf8_info表的索引,该表给出了属性的名称;
class文件内容举例:
  1. 代码
    public interface MyInterface {
        void hello();
    }
  2. 编译后其字节码如下图:

    • 常量池数"0009"表示后面紧接着有8个常量池项
    • 常量池索引1表示一个CONSTANT_Class_info表(07),它引用索引为7的常量池;
    • 常量池索引2表示一个CONSTANT_Class_info表(07),它引用索引为8的常量池;
    • 常量池索引3表示一个CONSTANT_Utf8_info表(01),其内容为hello(方法名);
    • 常量池索引4表示一个CONSTANT_Utf8_info表(01),其内容为()V(方法参数与返回值);
    • 常量池索引5表示一个CONSTANT_Utf8_info表(01),其内容为SourceFile(某属性值);
    • 常量池索引6表示一个CONSTANT_Utf8_info表(01),其内容为MyInterface.java(某属性值);
    • 常量池索引7表示一个CONSTANT_Utf8_info表(01),其内容为MyInterface,被常量池索引1引用到(当前类);
    • 常量池索引8表示一个CONSTANT_Utf8_info表(01),其内容为java/lang/Object,被常量池索引2引用到(超类);
    • 访问标志"0601"表示是public(0001)、abstract(0400),且是接口(0200);
    • 当前类索引号"0001"表示指向常量池索引1,指明当前类为MyInterface;
    • 超类索引号"0002"表示指向常量池索引2,指明超类为java/lang/Object;
    • 实现的接口数"0000"表示没有实现任何接口;
    • 字段数"0000"表示该接口没有字段;
    • 方法数"0001"表示接口有一个方法;
    • 剩下的字节码为方法列表及属性列表;

二、特殊字符串

        全限定名

           常量池指向类或者接口时,给出的是全限定名,形如java/util/Hashtable;

        简单名称

       字段名和方法名以简单名称形式出现在常量池入口中,如上例中的常量池索引3中的"hello";

       描述符

  1. 指向字段和方法的符号引用还包含描述符字符串;字段的描述符给出了字段的类型,方法描述符给出了方法的返回值和方法参数的数量、类型以及顺序;
  2. 描述符使用上下文无关语法:斜体表示非终结符,等宽字体表示终结符;
  3. 如下所示:

  4. 基本类型终结符
    终结符类型
    Bbyte
    Cchar
    Ddouble
    Ffloat
    Iint
    Jlong
    Sshort
    Zboolean
  5. 描述符举例
    描述符说明
    Iint i;
    [Ljava/lang/Object;java.lang.Object[] obj;
    ([BII)Ljava/lang/String;String method(byte[] b, int i, int j)
    ZILjava/lang/String;II()Zboolean method(boolean b, int i, String s, int j, int k)
本文系转载,原文:http://diecui1202.iteye.com/blog/611476

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 《java jdk7学习笔记》之java三大平台
  • java类的装入
  • LR常用函数以及调用自定义函数
  • java类加载器体系结构
  • MySQL 导入数据
  • java虚拟机学习笔记——类型和对象的生命周期(第七章)
  • jQuery中的100个技巧(译)
  • 子类为什么不能重写父类的静态方法
  • 15.6.6 Configuring Thread Concurrency for InnoDB
  • java虚拟机学习笔记——连接模型(第八章)
  • JVM垃圾回收机制算法总结
  • java内存模型
  • 表单样式简单设计
  • JVM学习总结
  • C#设计模式-模板方法模式
  • “大数据应用场景”之隔壁老王(连载四)
  • Angular 响应式表单 基础例子
  • angular2开源库收集
  • Apache的80端口被占用以及访问时报错403
  • CSS居中完全指南——构建CSS居中决策树
  • es6--symbol
  • JavaScript对象详解
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • JS基础之数据类型、对象、原型、原型链、继承
  • Solarized Scheme
  • Spring声明式事务管理之一:五大属性分析
  • 好的网址,关于.net 4.0 ,vs 2010
  • 你不可错过的前端面试题(一)
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 前端自动化解决方案
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​TypeScript都不会用,也敢说会前端?
  • #565. 查找之大编号
  • ${factoryList }后面有空格不影响
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (day18) leetcode 204.计数质数
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (pytorch进阶之路)扩散概率模型
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (二)WCF的Binding模型
  • (二)测试工具
  • (附源码)python旅游推荐系统 毕业设计 250623
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (转)memcache、redis缓存
  • (转)甲方乙方——赵民谈找工作
  • 、写入Shellcode到注册表上线
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案