在上一次【https://www.cnblogs.com/webor2006/p/9723289.html】中已经对Java方法的静态分派在字节码中的表现了,也就是方法重载其实是一种静态分派的体现,这次来分析一下与之对应的动态分派机制,其表现就是方法的重写多态机制,下面先来看下代码:

很显然是一个多态相关的代码,但结果会打印啥呢,看一下:

这个结果比上一节的要容易理解一些,是符合预期的,那从字节码角度如何来解释该程序的输出呢,下面详细来用jclasslib来分析一下它的字节码流程,如下:

上面是整个main方法对应字节码相关的信息,咱们一行行来分析:

其实也就是对应这句代码,生成Apple的一个实例:

看一下该助记符的官网解释:

其实就是调用了Apple的构造方法,以上三个助记符操作都是由new关键所发挥的作用,继续:

其中astore_1表示是存储在局部变量表序列号为1的变量中,那为1的局部变量是啥呢,到局部变量表中瞅一下就知道啦,如下:

也就是apple嘛,刚好跟源码对应:

以上就完成了源码的第一句代码,同样的对于第二次代码对应的助记符信息也类似,如下:

其中astore_2是保存在序列号为2的局部变量中,如下:

也就是给orange局部变量赋值了,接下来看下一句代码:

看下字节码:

看下官方解释:

而局部变量中序号为1的则就是apple如下:

接着调用Apple的test方法,但是从字节码中看到invokevirtual指令带的参数是调用的Fruit.test方法。。但是实际运行结果其实就是调用的Apple的test方法呢:

那不invokevirtual指令跟实际结果对不上了么,其实这是之后要重点学习的,这里先略过,先往下继续过流程,接着就是下一句代码了:

字节码类似的如下:

当然啦字节码中看到的是调用的Fruit.test()方法,跟结果调用的是Orange.test()结果是不符的,这个也先略过,继续看下一行代码:

对应字节码:

跟之前的操作类似,就不多说了,其中可以看到astore_1还是存在索引为1的局部变量apple,也就是引用给更新了,接下再往下看:

对应字节码如下:

最后整个方法返回:

到此,整个字节码完全分析完了,但是!!上面对于invokevirtual指令存有疑问,所以下面来解决它,先来看下这个指令的一个调用流程:

这其实是涉及到方法的动态分派,它涉及到一个很重要的概念:方法的接收者,也就是说该方法是由哪个对象所调用的,而invokevirtual字节码指令涉及到多态查找的流程,具体流程是:

1、首先要操作数栈的栈顶去寻找到栈顶的元素所指向对象的实际类型。对应于咱们的实际程序而言:

实际类型就是Apple。

2、如果在类型当中寻找到了与常量池中描述符名称相同的方法,如下:

,并且也具备一些方法的访问权限,也就是说去找看有没有实际类型的方法签名是public void test()的方法,很显然是能找到的,如下:

,那么就直接返回目标方法【对于我们程序也就是Apple.test()】的直接引用,整个过程就结束了;而如果找不到实际类型的该方法,则会从子类往父类的这种层次关系依次对各个父类重复同样的查找过程,一直到查到为止,查找到则就执行相印的方法,而如果一直找不到则就会抛出异常了。

比较方法重载(overload)与方法重写(overwrite),我们可以得到这样一个结论:方法重载是静态的,是编译期行为;方法重写是动态的,是运行期行为。而对于区分是不是方法重载和方法重写最重要的一个表现则是看方法的接收者,也就是方法的调用者是谁,像方法重载的调用者是同一个对像,如下:

因为test()方法本来就属于MyTest5类当中的。

而方法重写的调用者是不同的,如下:

也就是其调用的对象是子类的,而对于字节码是相同的符号引用而在运行期会被解析成不同的直接引用,这一点就是Java方法多态性极其重要的一个表现,如何理解?

而在运行期这两个类型会被解析Apple和Orange这两个直接引用。

通过字节码分析Java方法的静态分派与动态分派机制的更多相关文章

  1. 通过字节码分析java中的switch语句

    在一次做题中遇到了switch的问题,由于对switch执行顺序的不了解,在这里简单的通过字节码的方式理解一下switch执行顺序(题目如下): public class Ag{ static pub ...

  2. 通过字节码分析Java异常处理机制

    在上一次[https://www.cnblogs.com/webor2006/p/9691523.html]初步对异常表相关的概念进行了了解,先来回顾一下: 其源代码也贴一下: 下面来看一下jclas ...

  3. 透过字节码分析java基本类型数组的内存分配方式。

    我们知道java中new方式创建的对象都是在堆中创建的,而局部变量对应的值存放在栈上.那么java中的int [] arr={1,2,3}是存放在什么地方的呢,int []arr = new int[ ...

  4. 透过字节码分析Java动态代理机制。

    一.创建动态代理代码 1.创建接口 public interface Subject { void request(); } 2.创建接口实现类 public class RealSubject im ...

  5. 重读《深入理解Java虚拟机》五、虚拟机如何执行字节码?程序方法如何被执行?虚拟机执行引擎的工作机制

    Class文件二进制字符流通过类加载器和虚拟机加载到内存(方法区)完成在内存上的布局和初始化后,虚拟机字节码执行引擎就可以执行相关代码实现程序所定义的功能.虚拟机执行引擎执行的对象是方法(均特指非本地 ...

  6. Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)

    前面我们说到多线程带来的风险,其中一个很重要的就是安全性,因为其重要性因此,放到本章来进行讲解,那么线程安全性问题产生的原因,我们这节将从底层字节码来进行分析. 一.问题引出 先看一段代码 packa ...

  7. Java字节码分析

    目录 Java字节码分析 查看字节码详细内容 javap 实例分析 Java字节码分析 对于源码的效率,但从源码来看有时无法分析出准确的结果,因为不同的编译器版本可能会将相同的源码编译成不同的字节码, ...

  8. Dalvik字节码的类型,方法与字段表示方法

    Dalvik字节码有着自己的类型,方法与字段表示方法,这些方法与Dalvik虚拟机指令集一起组成了一条条的Dalvik汇编代码. 1.类型 Dalvik字节码只有两种类型,基本类型与引用类型.Dalv ...

  9. JVM-String比较-字节码分析

    一道String字符串比较问题引发的字节码分析 public class a { public static void main(String[] args)throws Exception{ } p ...

随机推荐

  1. CentOS 7 vi常用命令

    用vi打开一个yum文件 vi /usr/bin/yum 按 i 键后  进入insert模式,进入insert模式后才能进行修改 修改完成后 按esc键进入command模式, 然后:wq 保存文件 ...

  2. 最新 好未来java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿. 好未来等10家互联网公司的校招Offer,因为某些自身原因最终选择了 好未来.6.7月主要是做系统复习.项目复盘.Leet ...

  3. 2017年度好视频,吴恩达、李飞飞、Hinton、OpenAI、NIPS、CVPR、CS231n全都在

    我们经常被问:机器翻译迭代了好几轮,专业翻译的饭碗都端不稳了,字幕组到底还能做什么? 对于这个问题,我们自己感受最深,却又来不及解释,就已经边感受边做地冲出去了很远,摸爬滚打了一整年. 其实,现在看来 ...

  4. Eureka如何剔除已经宕机的节点

    同一个服务部署了多个实例,在通过网关调用时会随机调用其中一个.但是,当某个服务挂掉之后,依然在注册中心中,依然会随机被调用到,调用时便会超时报错.(主要是开发测试或者演示时需要立即将失效的从注册中心剔 ...

  5. Oracle常用指令

    /**  为了清晰化的显示:所有固定命令都是用大写格式显示 SQL语法分类:DML,DDL,DCL (1)DML(Data Manipulation Language ,数据库操作语言): 数据:增加 ...

  6. 部署系统报404.有可能是tomcat存在多个进程

      今天对需求进行系统升级部署,本以为只需要几分钟的事,结果却遇到了怪事 我是用Jenkins集成部署的,之前都是点一下几分钟就可以了,结果这次部署完成之后 一直报404,一直打不开页面,很无奈,就去 ...

  7. (四)Resquest 知识点总结 (来自那些年的笔记)

    目录 URL和URI的区别 获取URL.URI 什么是HttpServletResquest 获取请求头中字段的内容 获取请求信息的数据 将客户机的请求变为一个流返回 常用的方法 request乱码问 ...

  8. 方法区(关于java虚拟机内存的那些事)

    <深入理解 java 虚拟机> 读书扩展 作者:淮左白衣 写于 2018年4月13日21:26:05 目录 方法区 图例(方法区中都保存什么) 类型信息 类型的常量池 (即运行时常量池) ...

  9. MogileFS操作指令

    使用mogtool来操作文件 加入文件:mogtool inject <file_name> <key_name> --trackers=192.168.1.106:7001 ...

  10. IDEA整合Jenkins界面化管理项目构建

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/WALK_MAN_wubiao/articl ...