在上一次【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. LNMP V1.4正式版本安装及新增Let's Encrypt一键安装和其他功能

    军哥的LNMP一键安装包已经有一些年头了,着实给需要在Linux VPS.服务器中安装WEB环境的用户提供不小的帮助,而且每年儿童节都会有较大版本的更新和升级.老左在二月份的时候有体验过LNMP V1 ...

  2. Spring Maven工程引入css,js

    1.CSS <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet" type="t ...

  3. ab webbench 网站测压解决

    ab 网站测压解决 ab –c 100 –n 100 http://192.168.1.117/forum.php (测试方式) 同时发100人发100个请求 ab –c 100 –n 1000 ht ...

  4. [转帖]MMU内存管理单元

    MMU内存管理单元 https://www.cnblogs.com/alantu2018/p/9002309.html 之前对这一块一直不理解 最近学习了点 CPU time slice 以及 con ...

  5. WCF-简单 配置文件

    一.服务端配置文件 主要包括 1.services 配置服务节点 <!--name 指的是契约实现类--> <service name="WcfLib.User2" ...

  6. (十一)El表达式详细介绍

    看之前,最好先看下 el表达式快速入门 本来将重点讲下 el表达式 能干嘛 : 目录 执行计算 获得 web 开发常用对象 关于 param 与 paramValues 的用法: 关于 header ...

  7. # VsCode 配置C++调试运行

    VsCode 配置C++调试运行 打开命令面板快捷键为F1,软件上写的Ctrl+Shift+P似乎没用 先安装插件使得可以运行 先自行在vsc扩展中搜索C++安装C/C++插件 再参考知乎专栏中安装c ...

  8. Windows下命令行Git无法显示中文问题解决方案

    Windows下Git设置编码正常显示中文: 在 CMD 下设置环境变量 set LESSCHARSET=utf-8 在 PowerShell 下设置环境变量 $env:LESSCHARSET='ut ...

  9. Elasticsearch 介绍及应用

    Elasticsearch简单介绍 Elasticsearch (ES)是一个基于Lucene构建的开源.分布式.RESTful 接口全文搜索引擎.Elasticsearch 还是一个分布式文档数据库 ...

  10. 怎样通过混入(Mixin)实现多继承

    js不提供现成的多重继承的方法, 但可以通过Object.assign()来手动实现: function Father1(name){ this.name = name; } function Fat ...