(6) 深入理解Java Class文件格式(五)
前情回顾
本专栏的前几篇博文, 对class文件中的常量池进行了详细的解释。 前文讲解了常量池中的7种数据项, 它们分别是:
- CONSTANT_Utf8_info
- CONSTANT_NameAndType_info
- CONSTANT_Integer_info
- CONSTANT_Float_info
- CONSTANT_Long_info
- CONSTANT_Double_info
- CONSTANT_String_info
常量池中各数据项类型详解(续)
(8) CONSTANT_Class_info
(9) CONSTANT_Fieldref_info
- package com.jg.zhang;
- public class TestInt {
- int a = 10;
- void print(){
- System.out.println(a);
- }
- }
在print方法中, 引用了本类中的字段a。 代码很简单, 我们一眼就可以看到print方法中是如何引用本类中定义的字段a的。 那么在class文件中, 对字段a的引用是如何描述的呢? 下面我们将这段代码使用javap反编译, 给出简化后的反编译结果:
- Constant pool:
- #1 = Class #2 // com/jg/zhang/TestInt
- #2 = Utf8 com/jg/zhang/TestInt
- ......
- #5 = Utf8 a
- #6 = Utf8 I
- ......
- #12 = Fieldref #1.#13 // com/jg/zhang/TestInt.a:I
- #13 = NameAndType #5:#6 // a:I
- ......
- {
- void print();
- flags:
- Code:
- stack=2, locals=1, args_size=1
- 0: getstatic #19 // Field java/lang/System.out:Ljava/io/PrintStream;
- 3: aload_0
- 4: getfield #12 // Field a:I
- 7: invokevirtual #25 // Method java/io/PrintStream.println:(I)V
- 10: return
- }
(10) CONSTANT_Methodref_info
下面结合实际代码来说明, 代码如下:
- package com.jg.zhang;
- public class Programer {
- Computer computer;
- public Programer(Computer computer){
- this.computer = computer;
- }
- public void doWork(){
- computer.calculate();
- }
- }
- package com.jg.zhang;
- public class Computer {
- public void calculate() {
- System.out.println("working...");
- }
- }
- Constant pool:
- .........
- #12 = Utf8 ()V
- #20 = Methodref #21.#23 // com/jg/zhang/Computer.calculate:()V
- #21 = Class #22 // com/jg/zhang/Computer
- #22 = Utf8 com/jg/zhang/Computer
- #23 = NameAndType #24:#12 // calculate:()V
- #24 = Utf8 calculate
- {
- com.jg.zhang.Computer computer;
- flags:
- .........
- public void doWork();
- flags: ACC_PUBLIC
- Code:
- stack=1, locals=1, args_size=1
- 0: aload_0
- 1: getfield #13 // Field computer:Lcom/jg/zhang/Computer;
- 4: invokevirtual #20 // Method com/jg/zhang/Computer.calculate:()V
- 7: return
- }
可以看到, doWork方法的位置为4的字节码指令invokevirtual引用了索引为20的常量池数据项, 常量池中索引为20的数据项是一个CONSTANT_Methodref_info, 这个CONSTANT_Methodref_info又引用了索引为21和23的两个数据项, 索引为21的数据项是一个CONSTANT_Class_info, 这个CONSTANT_Class_info数据项又引用了索引为22的数据项, 索引为22的数据项是一个CONSTANT_Utf8_info , 他存储了被引用的Computer类中的calculate方法所在的类的全限定名com/jg/zhang/Computer 。 而CONSTANT_Methodref_info所引用的索引为23的数据项是一个CONSTANT_NameAndType_info, 它又引用了两个数据项, 分别为第24项和第12项, 这是两个CONSTANT_Utf8_info , 分别存储了被引用的方法calculate的方法名calculate, 和该方法的描述符()V 。
(11) CONSTANT_InterfaceMethodref_info
下面结合实际代码来说明, 代码如下:
- package com.jg.zhang;
- public class Plane {
- IFlyable flyable;
- void flyToSky(){
- flyable.fly();
- }
- }
- package com.jg.zhang;
- public interface IFlyable {
- void fly();
- }
在上面的代码中, 定义可一个类Plane, 在这个类中有一个IFlyable接口类型的字段flyable, 然后在Plane的flyToSky方法中调用了IFlyable中的fly方法。 这就是源代码中对一个接口中的方法的引用方式, 下面我们反编译Plane, 看看在class文件层面, 对一个接口中的方法的引用是如何描述的。
下面给出反编译结果, 为了简洁期间, 省略了一些不相关的内容:
- Constant pool:
- .........
- #8 = Utf8 ()V
- #19 = InterfaceMethodref #20.#22 // com/jg/zhang/IFlyable.fly:()V
- #20 = Class #21 // com/jg/zhang/IFlyable
- #21 = Utf8 com/jg/zhang/IFlyable
- #22 = NameAndType #23:#8 // fly:()V
- #23 = Utf8 fly
- {
- .........
- com.jg.zhang.IFlyable flyable;
- flags:
- .........
- void flyToSky();
- flags:
- Code:
- stack=1, locals=1, args_size=1
- 0: aload_0
- 1: getfield #17 // Field flyable:Lcom/jg/zhang/IFlyable;
- 4: invokeinterface #19, 1 // InterfaceMethod com/jg/zhang/IFlyable.fly:()V
- 9: return
- }
可以看到, flyToSky方法的位置为4的字节码指令invokeinterface引用了索引为19的常量池数据项, 常量池中索引为19的数据项是一个CONSTANT_InterfaceMethodref_info, 这个CONSTANT_InterfaceMethodref_info又引用了索引为20和22的两个数据项, 索引为20的数据项是一个CONSTANT_Class_info, 这个CONSTANT_Class_info数据项又引用了索引为21的数据项, 索引为21的数据项是一个CONSTANT_Utf8_info , 他存储了被引用的方法fly所在的接口的全限定名com/jg/zhang/IFlyable 。 而CONSTANT_InterfaceMethodref_info所引用的索引为22的数据项是一个CONSTANT_NameAndType_info, 它又引用了两个数据项, 分别为第23项和第8项, 这是两个CONSTANT_Utf8_info , 分别存储了被引用的方法fly的方法名fly, 和该方法的描述符()V 。
总结
(6) 深入理解Java Class文件格式(五)的更多相关文章
- (8) 深入理解Java Class文件格式(七)
		转载:http://blog.csdn.net/zhangjg_blog/article/details/22091529 本专栏列前面的一系列博客, 对Class文件中的一部分数据项进行了介绍. 本 ... 
- (4) 深入理解Java Class文件格式(三)
		转载:http://blog.csdn.net/zhangjg_blog/article/details/21557357 首先, 让我们回顾一下关于class文件格式的之前两篇博客的主要内容. 在 ... 
- (5) 深入理解Java Class文件格式(四)
		转载:http://blog.csdn.net/zhangjg_blog/article/details/21658415 前情回顾 在上一篇博客深入理解Java Class文件格式(三) 中, ... 
- (3) 深入理解Java Class文件格式(二)
		好文转载:http://blog.csdn.net/zhangjg_blog/article/details/21487287 在上一篇文章 深入理解Java Class文件格式(一) 中, 介绍了c ... 
- (2) 深入理解Java Class文件格式(一)
		好文转载:http://blog.csdn.net/zhangjg_blog/article/details/21486985 Class文件在Java体系结构中的位置和作用 在上一篇博客中, 大致讲 ... 
- 【由浅入深理解java集合】(五)——集合 Map
		前面已经介绍完了Collection接口下的集合实现类,今天我们来介绍Map接口下的两个重要的集合实现类HashMap,TreeMap.关于Map的一些通用介绍,可以参考第一篇文章.由于Map与Lis ... 
- 深入理解java虚拟机第五部分高效并发
		volatile是java虚拟机提供最轻量级的同步机制. volatile两个特性:1,保证同步的变量对所有线程是可见的.虽然对所有线程是即时可见的,但是却不保证原子性,也就是不保证线程安全,比如对于 ... 
- 快速理解Java中的五种单例模式
		解法一:只适合单线程环境(不好) package test; /** * @author xiaoping * */ public class Singleton { private static S ... 
- 重读《深入理解Java虚拟机》五、虚拟机如何执行字节码?程序方法如何被执行?虚拟机执行引擎的工作机制
		Class文件二进制字符流通过类加载器和虚拟机加载到内存(方法区)完成在内存上的布局和初始化后,虚拟机字节码执行引擎就可以执行相关代码实现程序所定义的功能.虚拟机执行引擎执行的对象是方法(均特指非本地 ... 
随机推荐
- 获取Java系统相关信息
			package com.test; import java.util.Properties; import java.util.Map.Entry; import org.junit.Test; pu ... 
- 阶乘之和--nyoj91
			描述 给你一个非负数整数n,判断n是不是一些数(这些数不允许重复使用,且为正数)的阶乘之和,如9=1!+2!+3!,如果是,则输出Yes,否则输出No: 输入 第一行有一个整数0<m<10 ... 
- Windows NT驱动程序的基本结构和实例
			Windows驱动程序分为两类:一类是不支持即插即用功能的NT式驱动程序:另一类是支持即插即用功能的WDM驱动程序. NT式驱动的基本结构: 1)驱动加载过程与驱动入口函数DriverEntry: 驱 ... 
- asp.net identity 2.2.0 中角色启用和基本使用(五)
			建立控制器UsersAdminController 第一步:在controllers文件夹上点右键>添加>控制器, 我这里选的是“MVC5 控制器-空”,名称设置为:UsersAdminC ... 
- c语言的输入输出函数
			参考文章: http://blog.sina.com.cn/s/blog_784f40b80100psg9.html C语言输入输出函数分为两类: 1.格式化输入输出函数 2.非格式化输入输出 --- ... 
- MongoDB安装并设置为windows服务以使其开机自启
			在MongoDB的官方下载windows平台的压缩zip文件,地址:https://www.mongodb.org/dr/fastdl.mongodb.org/win32/mongodb-win32- ... 
- Extjs 图片的自动缩放
			function resizeImage(obj) { var width = Ext.getCmp('welcome').getWidth(); //welcome 为一Panel的id 分割线下的 ... 
- Eclipse Memory Analyzer,内存泄漏插件,安装使用一条龙
			网上文档很多,但最初都有问题.整理一份,作为备份.使用过程:开发代码写完后,对可能出现内存溢出的代码,添加配置文件,生成.hprof文件,用memory Analyzer分析排查问题,且泄漏内存大小可 ... 
- Python开发【第三章】:Python函数介绍
			一. 函数介绍 1.函数是什么? 在学习函数之前,一直遵循面向过程编程,即根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复 ... 
- iOS ARC中CTCallCenter没用,无法监听电话的解决方案
			今天在尝试使用CTCallCenter进行电话监听时,发现一直无法捕获电话状态改变的事件,研究了一番之后找到了解决方案,在这里分享给大家. 首先使用CTCallCenter监听电话的代码如下: CTC ... 
