JVM方法调用invokevirtual详解

 更新时间:2022年03月21日 10:32:19   作者:codeZhu  
JVM调用方法有五条指令,分别是invokestatic,invokespecial,invokevirtual,invokeinterface,invokedynamic,这篇文章主要说明invokevirtual方法的调用问题,本文通过实例代码给大家介绍的非常详细,需要的朋友参考下吧

  在java代码运行期间,方法间的调用可以说是最为频繁的了,那么这些方法间的调用在底层的虚拟机又做了什么事情呢?现在就让我们揭开那道神秘的面纱。

  JVM调用方法有五条指令,分别是invokestatic,invokespecial,invokevirtual,invokeinterface,invokedynamic。invokestatic用来调用静态方法;invokespecial用来调用私有方法,父类方法(super.),类构造器方法;invokeinterface调用接口方法;invokedynamic方法动态执行;invokevirtual调用所有虚方法,即除了以上的方法外全用invokevirtual调用。

  这篇文章主要是说明invokevirtual方法的调用,以一个例子来说明。

class Father{
    public void fMe(){
        System.out.println("fMe");
        fMe1();//invovespecial调用
        System.out.println(this);
        this.fMe1();//invovespecial调用
    }
    private void fMe1(){
        System.out.println("fMe1");
}
class Son extends Father{  public void fMe1(){        System.out.println("sMe1");    }
public class ThisTest{
    public static void main(String[] args) {
        Father test = new Son();
        test.fMe();//编译时指向父类中国的fMe(),在运行时由于是invokevirtual调用,因此test将变成实际类型Son,如果Son中有Fme(),就调用Son自己的,若没有就调用父类的

  父类Father中有一个public方法fMe()和一个私有方法fMe1(),子类中没有对其方法覆盖,在测试类ThisTest中 Father test = new Son();,并调用fMe(),再在fMe()中调用自己的私有方法fMe1()。在如上的几个方法调用中test.fMe()是invokevirtual调用,编译时指向父类中国的fMe(),在运行时由于是invokevirtual调用,因此test将变成实际类型Son,如果Son中有fMe(),就调用Son自己的,若没有就调用父类的,此时是调用父类的;在父类中 的fMe1()是invovespecial调用。疑问(也是写这篇文章的目的):上面的this代表Son,既然是invovespecial调用,那么应该是调用Son的fMe1()才对啊,为什么是调用父类的fMe1()。(虽然感觉好无厘头,明明是private方法了,肯定只有这样的调用了)

  下面给出我自己的理解,不知道对不对!

  上面的用this调用的时候,我觉得在编译期间,this代表的是Father类,而不是Son类,正因为是这样,在用invovespecial字节码调用的时候采用在编译器就确定好了指向父类fMe1()方法,而不是子类的方法。为了确定我说的,我采用了两种方式去验证:1是用MyEclipse的动态提示,2是将fMe1()方法改为public,这样在字节码指invokevirtual调用的时候看是不是在运行期间改变this为实际类型Son类,即是不是去调用子类的fMe1()方法。

  1:我在MyEclipse中用提示键得到如下,可以看出只有父类的两个方法,并没有子类Son的方法。

2、在我将fMe1()方法改为public后确实是调用的是子类的方法。

class Father{
    public void fMe(){
        System.out.println("fMe");
        this.
        fMe1();//invovespecial调用
        System.out.println(this);
        this.fMe1();//invovespecial调用
    }
     
    public void fMe1(){
        System.out.println("fMe1");
}
 
class Son extends Father{
        System.out.println("sMe1");
public class ThisTest{
    public static void main(String[] args) {
        Father test = new Son();
        test.fMe();//编译时指向父类中国的fMe(),在运行时由于是invokevirtual调用,因此test将变成实际类型Son,如果Son中有Fme(),就调用Son自己的,若没有就调用父类的

  这是在看invokevirtual想到的,不知道对不对,如果谁能解开我的这个疑惑真是会十分感谢。

到此这篇关于JVM方法调用invokevirtual的文章就介绍到这了,更多相关JVM方法调用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot实现文件下载的四种方式

    SpringBoot实现文件下载的四种方式

    本文主要介绍了SpringBoot实现文件下载的四种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-11-11
  • springboot-2.3.x最新版源码阅读环境搭建(基于gradle构建)

    springboot-2.3.x最新版源码阅读环境搭建(基于gradle构建)

    这篇文章主要介绍了springboot-2.3.x最新版源码阅读环境搭建(基于gradle构建),需要的朋友可以参考下
    2020-08-08
  • mybatis.type-aliases-package之巨坑的解决

    mybatis.type-aliases-package之巨坑的解决

    这篇文章主要介绍了mybatis.type-aliases-package之巨坑的解决,具有很好的参考价值,希望对大家有所帮助。
    2021-09-09
  • JavaWeb BeanUtils信息类原理详解

    JavaWeb BeanUtils信息类原理详解

    这篇文章主要介绍了JavaWeb BeanUtils信息类原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Java实现茶叶售卖商城系统(java+SSM+JSP+EasyUi+mysql)

    Java实现茶叶售卖商城系统(java+SSM+JSP+EasyUi+mysql)

    这篇文章主要介绍了基于SSM框架实现的一个茶叶售卖商城系统,应用到的技术有Jsp、SSM 、EasyUi,文中的示例代码具有一定的学习价值,需要的朋友可以参考一下
    2021-12-12
  • 关于ThreadLocal对request和response的用法说明

    关于ThreadLocal对request和response的用法说明

    这篇文章主要介绍了关于ThreadLocal对request和response的用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Java多线程连续打印abc实现方法详解

    Java多线程连续打印abc实现方法详解

    这篇文章主要介绍了Java多线程连续打印abc实现方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Java批量插入数据的代码实现

    Java批量插入数据的代码实现

    日常工作或者学习中,可能会遇到批量插入数据的需求,一般情况下数据量少的时候,我们会直接调用批量接口插入数据即可,当数据量特别大时,我们就会用到分批插入数据,所以本文给大家介绍了Java批量插入数据的代码实现,需要的朋友可以参考下
    2024-01-01
  • Java程序执行cmd命令全过程

    Java程序执行cmd命令全过程

    这篇文章主要介绍了Java程序执行cmd命令全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Java手动实现Redis的LRU缓存机制

    Java手动实现Redis的LRU缓存机制

    在Java中LRU的实现方式是使用HashMap结合双向链表,HashMap的值是双向链表的节点,双向链表的节点也保存一份key value。
    2021-05-05

最新评论