在上一次【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. eclipse 解决POM文件错误:org.apache.maven.archiver.MavenArchiver.getManifest(org.apache.maven.project.MavenProject, org.apache.maven.archiver.MavenArchiveConfiguration)

    解决方案: 更新eclipse中的maven插件 1.1 Help -> Install New Software -> Add 1.2 Location中输入 http://repo1. ...

  2. AutoMapper扩展帮助类

    /// <summary> /// AutoMapper扩展帮助类 /// </summary> public static class AutoMapperExtension ...

  3. 工作总结---CTO(张王岩)的笔记--

    1. 语言的基础:  变量.控制语句.方法 .数组 2. 面向对象  OOP 3. 容器  存储数据.分析数据  介绍[IO  File   字节流    字符流  CommonsIO] input  ...

  4. todo---jaxen

  5. Java的设计模式之开篇(1)

    什么是设计模式呢?这个问题曾经一直困扰着我,以前我一直以为这是门新的技术,但是随着工作年限和工作经验的增加,其实设计模式就是已经在众多软件系统得到验证的成功的并且可复用的技术方案或者解决问题的方案.J ...

  6. (五)Respose 知识点总结 (来自那些年的笔记)

    目录 HttpServletResponse简介 向客户机写数据 HttpServletResponse应用 打印中文,让浏览器显示不乱码 : 下载文件 输出随机图片(验证码) 不要缓存 图片的src ...

  7. malloc/free和new/delete详解与应用

    C++面试经常会问到关于malloc/free和new/delete的区别,网上有不同版本的解释,这里总结下并加上个人理解和使用. 两者相同点 1.都可以申请动态堆内存. 两者不同点 1.new/de ...

  8. Solr介绍 入门练习

    1.1 Solr是什么 Solr是一个基于全文检索的企业级应用服务器. 全文检索:可以输入一段文字,通过分词检索数据!!(复习) 应用服务器:它是单独的服务. 1.2 Solr能做什么 它就是用于做全 ...

  9. (二)第一个mybatis项目

    1. 引包 本例中使用maven构造项目,所以只需配置依赖即可引相应的包. pom.xml <project xmlns="http://maven.apache.org/POM/4. ...

  10. LeetCode 1103. Distribute Candies to People

    1103. Distribute Candies to People(分糖果||) 链接:https://leetcode-cn.com/problems/distribute-candies-to- ...