《深入Java虚拟机学习笔记》- 第6章 class文件
一、class文件内容
Java class文件是对Java程序二进制文件格式的精确定义。每一个Java class文件都对一个Java类或者Java接口作出了全面描述。一个class文件只 能包含一个类或接口;
class文件内容按顺序如下(ClassFile表中各项简介如下):
- magic(魔数)-u4
- 0xCAFEBABE,其作用在于可以轻松辨别出Java class文件和非Java class文件;
- minor_version-u2和major_version-u2(次、主版本号)
- 对于虚拟机来说,主次版本号确定了特定的class文件格式,通常只有给定主版本号和一系列次版本号后,虚拟机才能读取该class文件;
- 如下图所示
第5、6字节表示次版本号=0
第7、8字节表示主版本号=50(高位在前)
- constant_pool_count-u2和constant_pool(常量池)
- 常量池的数量为constant_pool_count-1,其索引从1开始;
- 除直接常量外,常量池还包括类和接口的全限定名、字段的名称和描述符以及方法的名称和描述符等符号引用;
- 每个常量池入口都有一个字节的标志,这个标志指出了列表中该位置的常量类型。虚拟机获取这个标志后,就知道在标志后面的常量类型了;其中每一 个标志都有一个相对应的表结构来描述该常量池;具体类型如下表所示:
- access_flags(访问标志)-u2
- 访问标志展示了文件中类或接口的如下信息: 标志名 值 设置后的含义
ACC_PUBLIC 0x0001 public类型 ACC_FINAL 0x0010 类为final类型 ACC_SUPER 0x0020 使用新型的invokespecial语义 ACC_INTERFACE 0x0200 接口类型,不是类类型 ACC_ABSTRACT 0x0400 abstract类型 附:invokespecial和invokevirtual
invokespecial指静态绑定后,由JVM产生调用的方法。如super(),以及super.someMethod(),都属于 invokespecial;
invokevirtual指动态绑定后,由JVM产生调用的方法。如obj.someMethod(),属于invokevirtual;
正是由于这两种绑定的不同,在子类覆盖超类的方法、并向上转型引用后,才产生了多态以及其他特殊的调用结果。
- 访问标志展示了文件中类或接口的如下信息: 标志名 值 设置后的含义
- this_class-u2(当前类)
- 它是一个对常量池的索引,在this_class位置的常量池入口必须为CONSTANT_Class类型对应的表结构 CONSTANT_Class_info...;
- 下图显示了常量池的使用方法:
在CONSTANT_Utf8_info表的bytes里存放的即是当前类的全限定名字符串;
- super_class-u2(直接超类)
- 和this_class表示的内容相同;
- 除了java.lang.Object类以外,常量池索引super_class对于所有类均有效;
- 对于java.lang.Object,其super_class为0;
- 对于接口,其super_class指向的常量池为java.lang.Object;
- interfaces_count-u2和interfaces(接口列表)
- 保存该类直接实现或该接口所扩展的接口数量;
- 接口按implements子句和extends子句出现的顺序显现;
- interfaces表中的每一项都是对父接口的常量池的索引,该索引用CONSTANT_Class_info来描述;
- 如果接口数为0,则没有interfaces表;
- fields_count-u2和fields(字段列表)
- 只有在class文件中由类或接口声明了的字段才在fields列表中列出,不列出从超类或父接口中继承而来的字段;
- fields列表可能会包含在对应的Java源文件中没有叙述的字段,这是因为Java编译器可能会在编译时向类或者接口添加字段;如对一个内部类的fields列表来说,为了保持对外围类实例的引用,Java编译器会为每个外围类实例添加实例变量 ;
- 第个field_info表包含以下字段信息:
- 字段名字
- 字段描述符和修饰符
- 如果该字段被声明为final,则还包含其常量值;
- methods_count-u2和methods(方法列表)
- methods_count表示该类或接口中所声明的所有方法的总计数,不包括超类或都父接口中继承来的方法;
- methods列表中包含以下信息:
- 方法名和描述符(方法的返回值类型和参数类型)
- 如果方法即不是抽象的,也不是本地的,则还包含方法局部变量所需的栈空间长度、为方法所捕获的异常表、字节码序列以及可选的行数和局部变量 表
- 如果方法能够抛出任何已验证异常,则methods列表就会包括一个关于这些已验证异常的列 表
- attributes_count-u2和attributes(属性列表)
- class文件中最后的部分是属性,它给出了该文件中类或接口所定义的属性的基本信息;
- 每个attribute_info表的第一项是指向常量池中CONSTANT_Utf8_info表的索引,该表给出了属性的名称;
class文件内容举例
- 代码
public interface MyInterface {
void hello();
} - 编译后其字节码如下图:
- 常量池数"0009"表示后面紧接着有8个常量池项
- 常量池索引1表示一个CONSTANT_Class_info表(07),它引用索引为7的常量池;
- 常量池索引1表示一个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";
描述符
- 指向字段和方法的符号引用还包含描述符字符串;字段的描述符给出了字段的类型,方法描述符给出了方法的返回值和方法参数的数量、类型以及顺序;
- 描述符使用上下文无关语法:斜体表示非终结符,等宽字体表示终结符;
- 如下所示:
- 基本类型终结符 终结符 类型
B byte C char D double F float I int J long S short Z boolean - 描述符举例 描述符 说明
I int i; [Ljava/lang/Object; java.lang.Object[] obj; ([BII)Ljava/lang/String; String method(byte[] b, int i, int j) ZILjava/lang/String;II()Z boolean method(boolean b, int i, String s, int j, int k)
《深入Java虚拟机学习笔记》- 第6章 class文件的更多相关文章
- 《深入Java虚拟机学习笔记》- 第19章 方法的调用与返回
<深入Java虚拟机学习笔记>- 第19章 方法的调用与返回
- 《深入Java虚拟机学习笔记》- 第16章 控制流
<深入Java虚拟机学习笔记>- 第16章 控制流
- 《深入Java虚拟机学习笔记》- 第17章 异常
<深入Java虚拟机学习笔记>- 第17章 异常
- 《深入Java虚拟机学习笔记》- 第13章 逻辑运算
<深入Java虚拟机学习笔记>- 第13章 浮点运算
- 《深入Java虚拟机学习笔记》- 第14章 浮点运算
<深入Java虚拟机学习笔记>- 第13章 浮点运算
- 《深入Java虚拟机学习笔记》- 第8章 连接模型
Java虚拟机学习笔记(八)连接模型
- 《深入Java虚拟机学习笔记》- 第4章 网络移动性
Java虚拟机学习笔记(四)网络移动性
- 《深入Java虚拟机学习笔记》- 第2章 平台无关
Java虚拟机学习笔记(二)平台无关
- java JDK8 学习笔记——第16章 整合数据库
第十六章 整合数据库 16.1 JDBC入门 16.1.1 JDBC简介 1.JDBC是java联机数据库的标准规范.它定义了一组标准类与接口,标准API中的接口会有数据库厂商操作,称为JDBC驱动程 ...
- Java虚拟机学习笔记——JVM垃圾回收机制
Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...
随机推荐
- unity脚本的基础语法
基本的回调方法 Strat()方法:在游戏场景加载时被调用,在该方法内可以写一些游戏场景初始化之类的代码. update():在每一帧渲染之前被调用,大部分游戏代码在这里执行,除了物理部分的代码. F ...
- 然爸读书笔记(2013-4)----打造facebook
扎克伯格的真实一面 (1)在公司内部知无不言,扎克伯格在公司内部问答时间.尽可能回答员工的任何问题,保持足够的透明度. (2)员工只有做到对外守口如瓶,我们才能做到对内知无不言. (3)faceboo ...
- 1206: [HNOI2005]虚拟内存 - BZOJ
Description 操作系统中一种重要的存储管理技术就是虚拟内存技术.操作系统中允许进程同时运行,也就是并行.每个进程都有其相对独立的数据块(进程运行的过程中将对其进行读写操作).理想的情况下,这 ...
- CQRS学习——一个例子(其六)
[先上链接:http://pan.baidu.com/s/1o62AHbc ] 多图杀猫 先用一组图看看实现的功能: 添加一个功能 假定现在要添加一个书本录入的功能,那么执行如下的操作: 1.添加Co ...
- [转载]获取当前日期和农历的js代码
原文地址: http://www.cnblogs.com/Gnepner/archive/2011/09/07/2169822.html 获取当前日期时间: function GetCurrentDa ...
- PAT-乙级-1016. 部分A+B (15)
1016. 部分A+B (15) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 正整数A的“DA(为1位整数)部 ...
- PAT-乙级-1001. 害死人不偿命的(3n+1)猜想 (15)
1001. 害死人不偿命的(3n+1)猜想 (15) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 卡拉兹(Ca ...
- hdu 1087
动规 d[i]记录以第 i 个数结尾的最大值 #include <cstdio> #include <algorithm> #include <cstring> ...
- 定长内存池之BOOST::pool
内存池可有效降低动态申请内存的次数,减少与内核态的交互,提升系统性能,减少内存碎片,增加内存空间使用率,避免内存泄漏的可能性,这么多的优点,没有理由不在系统中使用该技术. 内存池分类: 1. ...
- SQLite入门与分析(四)---Page Cache之事务处理(1)
写在前面:从本章开始,将对SQLite的每个模块进行讨论.讨论的顺序按照我阅读SQLite的顺序来进行,由于项目的需要,以及时间关系,不能给出一个完整的计划,但是我会先讨论我认为比较重要的内容.本节讨 ...