• jvm是怎样调用方法的


    jvm内部有五种调用方法的指令

    invokeinterface	用以调用接口方法,在运行时搜索一个实现了这个接口方法的对象,找出适合的方法进行调用。(Invoke interface method)
    invokevirtual	指令用于调用对象的实例方法,根据对象的实际类型进行分派(Invoke instance method; dispatch based on class)
    invokestatic	用以调用类方法(Invoke a class (static) method )
    invokespecial	指令用于调用一些需要特殊处理的实例方法,包括实例初始化方法、私有方法和父类方法。(Invoke instance method; special handling for superclass, private, and instance initialization method invocations )
    invokedynamic	JDK1.7新加入的一个虚拟机指令,相比于之前的四条指令,他们的分派逻辑都是固化在JVM内部,而invokedynamic则用于处理新的方法分派:它允许应用级别的代码来确定执行哪一个方
    invokestatic和invokespecial是在编译器确定的,他们适用于不会发生重写的情况
    invokevirtual和invokeinterface	是虚方法,这两个指令在调用时,通过一张方法表来调用。

    看两个类

    public class Animal {
        protected void sleep(){
            System.out.println("动物能睡觉");
        }
    }
    
    
    
    
    
    public class Bird extends Animal implements Fly {
        @Override
        protected void sleep() {
            System.out.println("鸟会睡觉");
        }
    
        @Override
        public void fly() {
            System.out.println("鸟会飞");
        }
    
        public static void print() {
            System.out.println("这是鸟");
        }
    }
    
    
    

    两个类对应的方法表

    animal的方法表

    0
    sleep

    bird方法表

    0sleep
    1 fly

    如果重写父类的方法,父类方法的index和子类的一致,方便查找。

    由上可知,使用继承或实现会让程序变慢,因为需要查方法表,但是没有必要因为慢而放弃面向对象良好的设计,因为这个时间很短并且jvm还有针对虚方法的优化,内联缓存。

    内联缓存举个例子来说

    Animal animal = new Bird();

    animal.sleep();

    这个时候jvm缓存下bird对象和sleep方法,下次bird对象想要调用sleep方法时,缓存里存了bird的方法就不用去查表了。

  • 相关阅读:
    Ubuntu20.04本地安装Redash中文版
    ubuntu设置root密码
    qmake设置生成文件分类
    QML对象的构造函数和析构函数
    QString使用split按照某字符进行分解
    Qt的qDebug直接打印不添加头文件
    C++宏定义中的#
    Qt设置生成的文件路径
    QWidget禁止最大化
    js-去掉回车和空格
  • 原文地址:https://www.cnblogs.com/zhandouBlog/p/10350049.html
Copyright © 2020-2023  润新知