【jvm】方法的调用

目录

        • 一、方法的调用
        • 二、非虚方法
        • 三、虚方法
        • 四、虚拟机调用指令
          • 4.1 普通调用指令
          • 4.2 动态调用指令
        • 五、代码示例
          • 5.1 父类
          • 5.2 子类
          • 5.3 接口
          • 5.4 接口实现
        • 六、方法指令
        • 七、说明
        • 八、invokedynamic指令
          • 8.1 说明
          • 8.2 代码示例
          • 8.3 main方法指令
        • 九、方法重写的本质
        • 十、虚方法表

一、方法的调用
  • 1.在jvm中,将符号引用转换为调用方法的直接引用与方法的绑定机制相关
  • 2.静态链接:当一个字节码文件被装载进jvm内部时,如果被调用的目标方法在编译期可知,且运行期保持不变时。这种情况下将调用方法的符号引用转换为直接引用的过程称为静态链接
  • 3.动态链接:如果被调用的方法在编译期无法被确定下来,也就是说,只能够在程序运行期将调用方法的符号引用转换为直接引用,由于这种引用转换过程具备动态性,因此也就被称之为动态链接。
  • 4.对应的方法的绑定机制为:早期绑定 (Early Binding)和晚期绑定(Late Binding)。绑定是一个字段、方法或者类在符号引用被替换为直接引用的过程,这仅仅发生一次。
  • 5.早期绑定:早期绑定就是指被调用的目标方法如果在编译期可知,且运行期保持不变时即可将这个方法与所属的类型进行绑定,这样一来,由于明确了被调用的目标方法究竟是哪一个,因此也就可以使用静态链接的方式将符号引用转换为直接引用。
  • 6.晚期绑定:如果被调用的方法在编译期无法被确定下来,只能够在程序运行期根据实际的类型绑定相关的方法,这种绑定方式也就被称之为晚期绑定
  • 7.随着高级语言的横空出世,类似于Java一样的基于面向对象的编程语言如今越来越多,尽管这类编程语言在语法风格上存在一定的差别,但是它们彼此之间始终保持着一个共性,那就是都支持封装、继承和多态等面向对象特性既然这一类的编程语言具备多态特性,那么自然也就具备早期绑定和晚期绑定两种绑定方式。
  • 8.Java中任何一个普通的方法其实都具备虚函数的特征,它们相当于c++语言中的虚函数 (c++中则需要使用关键字virtual来显式定义)。如果在Java程序中不希望某个方法拥有虚函数的特征时,则可以使用关键字final来标记这个方法。
二、非虚方法
  • 1.如果方法在编译期就确定了具体的调用版本,这个版本在运行时是不可变的这样的方法称为非虚方法
  • 2.静态方法、私有方法、fina1方法、实例构造器、父类方法都是非虚方法
  • 3.其他方法称为虚方法
三、虚方法
  • 1.子类对象的多态性的使用前提是类的继承关系和方法的重写
  • 2.编译期间无法确认的方法称为虚方法
四、虚拟机调用指令
4.1 普通调用指令
  • 1.invokestatic:调用静态方法,解析阶段确定唯一方法版本
  • 2.invokespecial:调用方法、私有及父类方法,解析阶段确定唯一方法版本
  • 3.invokevirtual:调用所有虚方法
  • 4.invokeinterface:调用接口方法
  • 5.上述4条指令固化在虚拟机内部,方法的调用执行不可人为干预
4.2 动态调用指令
  • 1.invokedynamic:动态解析出需要调用的方法,然后执行
  • 2.invokedynamic指令则支持由用户确定方法版本。
  • 3.其中invokestatic指令和invokespecial指令调用的方法称为非虚方法,其余的 (final修饰的除外) 称为虚方法。
五、代码示例
5.1 父类
package com.learning.stack.method_invoke;/*** @Author wangyouhui* @Description 父类**/
public class Father {public Father(){System.out.println("father的构造器");}public static void staticMethod(){System.out.println("father的static方法");}public final void finalMethod(){System.out.println("father的final方法");}public void commonMethod(){System.out.println("father的common方法");}
}
5.2 子类
package com.learning.stack.method_invoke;/*** @Author wangyouhui* @Description 子类**/
public class Son extends Father{public Son(){// 1 invokespecial #1 <com/learning/stack/method_invoke/Father.<init> : ()V>super();}public Son(int age){// 1 invokespecial #2 <com/learning/stack/method_invoke/Son.<init> : ()V>this();}// 静态方法不能被重写,因此该方法不是重写父类的静态方法public static void staticMethod(){System.out.println("son的static方法");}private void privateMethod(){System.out.println("son的private方法");}public void info(){}public void show(){// 0 invokestatic #7 <com/learning/stack/method_invoke/Son.staticMethod : ()V>staticMethod();// 3 invokestatic #8 <com/learning/stack/method_invoke/Father.staticMethod : ()V>super.staticMethod();// 7 invokespecial #9 <com/learning/stack/method_invoke/Son.privateMethod : ()V>privateMethod();// 11 invokespecial #10 <com/learning/stack/method_invoke/Father.commonMethod : ()V>super.commonMethod();// 15 invokevirtual #11 <com/learning/stack/method_invoke/Son.finalMethod : ()V>finalMethod();// 19 invokevirtual #12 <com/learning/stack/method_invoke/Son.commonMethod : ()V>commonMethod();// 23 invokevirtual #13 <com/learning/stack/method_invoke/Son.info : ()V>info();MethodInterface methodInterface = new MethodInterfaceImpl();// 35 invokeinterface #16 <com/learning/stack/method_invoke/MethodInterface.method : ()V> count 1methodInterface.method();}
}
5.3 接口
package com.learning.stack.method_invoke;/*** @Author wangyouhui* @Description 接口**/
public interface MethodInterface {void method();
}
5.4 接口实现
package com.learning.stack.method_invoke;/*** @Author wangyouhui* @Description 接口实现类**/
public class MethodInterfaceImpl implements MethodInterface{@Overridepublic void method() {System.out.println("接口实现类实现method方法");}
}
六、方法指令
 0 invokestatic #7 <com/learning/stack/method_invoke/Son.staticMethod : ()V>3 invokestatic #8 <com/learning/stack/method_invoke/Father.staticMethod : ()V>6 aload_07 invokespecial #9 <com/learning/stack/method_invoke/Son.privateMethod : ()V>
10 aload_0
11 invokespecial #10 <com/learning/stack/method_invoke/Father.commonMethod : ()V>
14 aload_0
15 invokevirtual #11 <com/learning/stack/method_invoke/Son.finalMethod : ()V>
18 aload_0
19 invokevirtual #12 <com/learning/stack/method_invoke/Son.commonMethod : ()V>
22 aload_0
23 invokevirtual #13 <com/learning/stack/method_invoke/Son.info : ()V>
26 new #14 <com/learning/stack/method_invoke/MethodInterfaceImpl>
29 dup
30 invokespecial #15 <com/learning/stack/method_invoke/MethodInterfaceImpl.<init> : ()V>
33 astore_1
34 aload_1
35 invokeinterface #16 <com/learning/stack/method_invoke/MethodInterface.method : ()V> count 1
40 return
七、说明
  • 1.invokestatic指令和invokespecial指令调用的方法称为非虚方法
  • 2.finalMethod虽然指令是invokevirtual ,但final修饰的方法不能被重写,因此也认为此方法为非虚方法
  • 3.接口方法调用指令是invokeinterface,在编译期间无法确认是谁实现,因此也是虚方法
八、invokedynamic指令
8.1 说明
  • 1.JVM字节码指令集一直比较稳定,一直到Java7中才增加了invokedynamic指令,这是Java为了实现[动态类型语言] 支持而做的种改进。
  • 2.在Java7中并没有提供直接生成invokedynamic指令的方法,需要借助ASM这种底层字节码工具来产生invokedynamic指令。直到Java8的Lambda表达式的出现,invokedynamic指令的生成,在Java中才有了直接的生成方式。
  • 3.Java7中增加的动态语言类型支持的本质是对Java虚拟机规范的修改,而不是对Java语言规则的修改,这一块相对来讲比较复杂,增加了虚拟机中的方法调用,最直接的受益者就是运行在Java平台的动态语言的编译器
  • 4.动态类型语言和静态类型语言两者的区别就在于对类型的检查是在编译期还是在运行期,满足前者就是静态类型语言,反之是动态类型语言。
  • 5.静态类型语言是判断变量自身的类型信息;动态类型语言是判断变量值的类型信息,变量没有类型信息,变量值才有类型信息,这是动态语言的一个重要特征。
8.2 代码示例
package com.learning.stack.method_invoke.invoke_dynamic;/*** @Author wangyouhui* @Description invokedynamic**/
@FunctionalInterface
interface Func{public boolean func(String string);
}public class Lambda {public void invokedynamicMethod(Func func){return;}public static void main(String[] args) {Lambda lambda = new Lambda();Func func = s -> {return true;};lambda.invokedynamicMethod(func);lambda.invokedynamicMethod(s ->{return true;});}
}
8.3 main方法指令
 0 new #2 <com/learning/stack/method_invoke/invoke_dynamic/Lambda>3 dup4 invokespecial #3 <com/learning/stack/method_invoke/invoke_dynamic/Lambda.<init> : ()V>7 astore_18 invokedynamic #4 <func, BootstrapMethods #0>
13 astore_2
14 aload_1
15 aload_2
16 invokevirtual #5 <com/learning/stack/method_invoke/invoke_dynamic/Lambda.invokedynamicMethod : (Lcom/learning/stack/method_invoke/invoke_dynamic/Func;)V>
19 aload_1
20 invokedynamic #6 <func, BootstrapMethods #1>
25 invokevirtual #5 <com/learning/stack/method_invoke/invoke_dynamic/Lambda.invokedynamicMethod : (Lcom/learning/stack/method_invoke/invoke_dynamic/Func;)V>
28 return
九、方法重写的本质
  • 1. 找到操作数栈顶的第一个元素所执行的对象的实际类型,记作 C
  • 2. 如果在类型 C 中找到与常量中的描述符合简单名称都相符的方法则进行访问权限校验,如果通过则返回这个方法的直接引用,查找过程结束;如果不通过则返回java.lang,IllegalAccessError 异常。
  • 3. 否则,按照继承关系从下往上依次对 C 的各个父类进行第 2 步的搜索和验证过程。
  • 4. 如果始终没有找到合适的方法,则抛出 java.lang.AbstractMethodError异常
十、虚方法表
  • 1.在面向对象的编程中,会很频繁的使用到动态分派,如果在每次动态分派的过程中都要重新在类的方法元数据中搜索合适的目标的话就可能影响到执行效率。因此,为了提高性能,JM采用在类的方法区建立一个虚方法表(virtual method table) (非虚方法不会出现在表中) 来实现。使用索引表来代替查找
  • 2.每个类中都有一个虚方法表,表中存放着各个方法的实际入口
  • 3.虚方法表会在类加载的链接阶段被创建并开始初始化,类的变量初始值准备完成之后,JVM会把该类的方法表也初始化完毕。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/128179.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一篇博客读懂顺序表 —— Sequence-List

目录 一、顺序表的初始定义 1.1新建头文件和源文件 1.2 SeqList.h 中的准备工作 二、顺序表的初始化与销毁 三、首尾插入元素 四、首尾删除元素 五、中间插入元素 六、中间删除元素 七、查找指定元素下标 八、源代码 一、顺序表的初始定义 1.1新建头文件和源文件 当我…

大语言模型的学习路线和开源模型的学习材料《一》

文章目录 第一层 LLMs to Natural Language Processing (NLP)第一重 ChatGLM-6B 系列ChatGLM3ChatGLM2-6BChatGLM-6B第十重 BaichuanBaichuan2Baichuan-13Bbaichuan-7B第十一重 Llama2第二重 Stanford Alpaca 7B第三重 Chinese-LLaMA-Alpaca第四重 小羊驼 Vicuna第五重 MOSS第六…

流媒体服务实现H5实时预览视频

目录 背景方案业务实践细节注意 待办 背景 客户aws服务磁盘存储告急&#xff0c;最高可扩容16T。排查如下&#xff1a;主要是视频文件存在大量复制使用的情况。例如发布节目时复制、预览时复制&#xff0c;这样上传一份视频后最大会有四份拷贝&#xff08;预览、普通发布、互动…

vue3简单写导航anchor示例(支持点击高亮和滚动判断高亮)

1. 点击anchor, 相应的anchorlink高亮 function anchorClick(index) { forceStop.value true; time Date.now(); wheelRef.value.children[index].scrollIntoView({ block: start, behavior: smooth }); // 给一些延时, 再点亮anchor, 同时不再限制scrol…

微信小程序 人工智能志愿者服务活动报名系统uniAPP+vue

基于java语言设计并实现了人工智能志愿者服务APP。该APP基于B/S即所谓浏览器/服务器模式&#xff0c;应用SpringBoot框架与HBuilder X技术&#xff0c;选择MySQL作为后台数据库。系统主要包括用户、志愿活动、活动报名、活动签到、服务职责、服务排行等功能模块。 本文首先介绍…

Zynq-Linux移植学习笔记之64- 国产ZYNQ在linux下配置国产5396芯片

1、背景介绍 复旦微ZYNQ通过SPI配置国产JEM5396&#xff0c;框图如下&#xff1a; 现在需要在linux下的应用程序内配置JEM5396的寄存器。其中FMQL和进口的XILINX ZYNQ类似&#xff0c;JEM5396和进口的BCM5396兼容。因此可以参考进口ZYNQ在linux下配置BCM5396过程。Zynq-Linux移…

云服务器 centos 部署 code-server 并配置 c/c++ 环境

将你的云服务器改为 centos 8 为什么要将云服务器的操作系统改成 centos 8 呢&#xff1f;原因就是 centos 7 里面的配置满足不了 code-server 的需求。如果你使用的是 centos 7 那么就需要你升级一些东西&#xff0c;这个过程比较麻烦。我在 centos 7 上面运行 code-server 的…

关于linux系统的常用命令

常用命令 1.进入文件夹 cd 2.查看文件 ll //列表详情查看 ls //仅查看文件名 3.查看文件&#xff08;例如jar包&#xff09; ps aux|grep jar 4.端口操作 iptables -I INPUT -p tcp --dport 8089 -j ACCEPT #开放8089端口 iptables -L INPUT -n --line-numbers #显示开放的端…

k8s、pod

Pod k8s中的port【端口&#xff1a;30000-32767】 port &#xff1a;为Service 在 cluster IP 上暴露的端口 targetPort&#xff1a;对应容器映射在 pod 端口上 nodePort&#xff1a;可以通过k8s 集群外部使用 node IP node port 访问Service containerPort&#xff1a;容…

velero备份k8s集群

流程图 velero备份原理 本地 Velero 客户端发送备份指令。Kubernetes 集群内就会创建一个 Backup 对象。BackupController 监测 Backup 对象并开始备份过程。BackupController 会向 API Server 查询相关数据。BackupController 将查询到的数据备份到远端的对象存储。 velero的…

VScode配置 github 上传代码

初始化本地库 git init创建本地分支&#xff0c;需要和github分支名字一样 git checkout -b master本地仓库连接远程仓库 git remote add origin 自己的仓库地址云仓库代码同步到本地 git pull origin master上传代码 git push -u origin master

osg三角带

案例1 #include <osg/Geode> #include <osg/Geometry> #include <osgDB/Registry> #include <osgDB/WriteFile> #include <osg/Notify> #include <osg/PrimitiveSet> #include <osgViewer/Viewer> #include <osgUtil/Optimizer&g…

【数据结构】希尔排序

文章目录 前言一、希尔排序的演示图例二、希尔排序&#xff1a;插入排序的优化版本☆三、核心算法思路四、算法思路步骤&#xff08;一&#xff09;预排序 gap>1&#xff08;二&#xff09;gap1 插入排序 完成排序收尾 五、码源详解&#xff08;1&#xff09;ShellSort1 ——…

Linux CentOS7.9安装OpenJDK17

Linux CentOS7.9安装OpenJDK17 一、OpenJDK下载 清华大学开源软件镜像站 国内的站点&#xff0c;下载速度贼快 二、上传解压 文件上传到服务器后&#xff0c;解压命令&#xff1a; tar -zxvf jdk-xxxx-linux-x64.tar.gz三、配置环境 export JAVA_HOME/home/local/java/j…

idea 配置checkstyle全过程

checkstyle是提高代码质量,检查代码规范的很好用的一款工具&#xff0c;本文简单介绍一下集成的步骤&#xff0c;并提供一份完整的checkstyle的代码规范格式文件&#xff0c;以及常见的格式问题的解决方法。 一&#xff0c;安装 打开idea的文件选项&#xff0c;选择设置&…

搜维尔科技:scalefit生物力学人体工学软件分析!

人体工程学分析 21加载参数和头像显示 识别(隐藏的)健康风险 根据DGUV交通灯进行生物反馈(DIN/ISO) 实时应力分析 三维空间可视化 静态/动态肩载 用左/右赋值加载输入 腰椎间盘压缩计算 距离和定时器显示 带有运动跟踪的化身/视频叠加 外骨骼与CAD工作站仿真 CSV原始…

【机器学习合集】模型设计之残差网络 ->(个人学习记录笔记)

文章目录 模型设计之残差网络1. 什么是残差结构1.1 网络加深遇到的优化问题1.2 short connect技术 2. 残差网络及有效性理解2.1 残差网络 3. 残差网络的发展3.1 密集残差网络3.2 更宽的残差网络(wide resnet)3.3 分组残差网络3.4 Dual Path Network3.5 加权残差网络3.6 预激活残…

WIN11如何固定文件夹查看方式

找一个文件夹&#xff0c;设置成自己需要的视图方式 文件夹选项>查看>应用到文件夹 缺点&#xff1a;所有相同类型文件夹都会使用此视图

数据结构——线性表①(顺序表)

一、线性表定义 线性表是一种数据结构&#xff0c;它是由n个具有相同数据类型的数据元素a1,a2,…,an组成的有限序列。 其中&#xff0c;除第一个元素a1外&#xff0c;每一个元素有且只有一个直接前驱元素&#xff0c;除了最后一个元素an外&#xff0c;每一个元素有且只有一个…

【基带开发】AD936验证数据源是连续的

五字节 %% 加载数据文件 BD_fileID fopen(rxdata3qpb.bin,r); % 获取 文件ID DATA_BD fread(BD_fileID,Inf,uint8); % 读取 文件数据 fclose(BD_fileID); …