(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文件二进制字符流通过类加载器和虚拟机加载到内存(方法区)完成在内存上的布局和初始化后,虚拟机字节码执行引擎就可以执行相关代码实现程序所定义的功能.虚拟机执行引擎执行的对象是方法(均特指非本地 ...
随机推荐
- 关于 QRCode 的问题[C# 生成二维码固定大小]
一直在纠结了一天多的问题:就是为什么生成的二维码会随着内容多少的变化而变化大小,但是为什么网上做出来的二维码内容变化但是大小却没有变化?刚开始的时候我就一直围绕着是不是根据缩略图来做的,但是这个方法行 ...
- Asp文件锁定脚本
锁定指定文件 <% on error resume next server.ScriptTimeout= response.write "<form method=post> ...
- IOS第七天(3:UiTableView 模型和数据的分组的显示)
*************UiTableView模型和数据的分组的显示 #import "HMViewController.h" #import "HMHero.h&qu ...
- Python脚本模拟登录网页之GitHub篇
1. 通过Firefox配合插件Tamper Date获取登录时客户端向服务器端提交的数据, 并且发现authenticity_token这个字段每次登录时都不一样. POSTDATA=commit= ...
- rabbitmq之消息生命周期
参考:http://jzhihui.iteye.com/blog/1567232
- 交流从选择coding.net开始
之前提到我们需要coding.net(一个可以帮助你在线存放管理代码的地方,便于项目合作)来进行学习交流,它可以帮我们记录我们入门的点点滴滴,现在就简单介绍一下coding.net的注册及使用. 1. ...
- Nest查询示例
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- textkit 研究,mark一下,一个不错的开源库:MLLabel(但是没有文档)
别人写的一个基于textkit的封装: https://github.com/molon/MLLabel 基于textkit实现的支持富文本的label, 可实现自定义emoji表情等
- reporting service & wpf
WPF做Windows程序界面很好很强大,RDLC做报表免费又好用,如何将两者强强联合呢? 方法1: 可以直接在WPF项目中加入一个WinForm窗体,在这个窗体上进行报表操作,与一般的Wi ...
- sublime 常用插件
1.ConvertToUTF8 支持 GBK, BIG5, EUC-KR, EUC-JP, Shift_JIS 等编码的插件 2.Bracket Highlighter 用于匹配括号,引号和html标 ...