深入理解JVM虚拟机第二十八篇:详解JVM当中方法重写的本质和虚方法表

😉😉 欢迎加入我们的学习交流群呀:

✅✅1:这是孙哥suns给大家的福利!

✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料

🥭🥭3:QQ群:583783824   📚📚  工作微信:BigTreeJava 拉你进微信群,免费领取!

🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞

💞💞5:以上内容,进群免费领取呦~ 💞💞💞💞

知识回顾

        因为方法的重写的出现的,导致我们出现了虚方法这种调用方式。之前我们提到的静态方法、私有方法、final方法、实例构造器、父类方法都是非虚方法,是因为从这个角度来讲,是不存在方法的重写的,你仔细品位一下,确实是这么回事的。

一:方法的重写的本质

1:本质介绍

        第一步:当我们去调用一个对象的方法的时候,首先会将这个对象压入操作数栈,经过invokeVurtual字节码指令去尝试调用方法。此时,当前被调用方法的对象位于操作数栈的栈顶,然后这个对象的方法类型被记作Type

        第二步:如果在类型 Type中找到与常量中的描述符合、简单名称都相符的方法,则进行访问权限校验,如果通过也就是有权限,则返回这个方法的直接引用,查找过程结束。如果不通过,则返回java.lang.IllegalAccessError 异常,这是一个非法访问的异常。

        第三步:否则,按照继承关系从下往上依次对Type的各个父类进行第 2 步的搜索和验证过程

        第四步:如果始终没有找到合适的方法,则抛出 java.lang.AbstractMethodError异常。

2:IllegalAccessError介绍:

        程序试图访问或修改一个属性或调用一个方法,这个属性或方法,你没有权限访问。一般的,这个会引起编译器异常,换句话说,这个大概率发生在编译阶段。这个错误如果发生在运行时,就说明一个类发生了不兼容的改变。

        举个极端例子去理解这个事。本来我们程序线上玩的特别好,程序跑的很欢快。有个同学,修改bug的时候,顺手把某个方法的修饰符public给去掉了(修改了方法适用范围),服务启动后,那么其他类在之前调用这个方法的时候没有任何问题,但是真正运行的时候可能就完蛋了,这个异常就爆出来了。

二:虚方法表

1:虚方法表概念

        在面向对象的编程中,会很频繁的使用到动态分派也就是invokeVurtual字节码指令。

        如果在每次动态分派的过程中都要重新在类的方法元数据中搜索合适的目标的话就可能影响到执行效率。因此,为了提高性能,JVM采用在类的方法区建立一个虚方法表(virtual method table) (非虚方法不会出现在表中)来实现。使用索引表来代替查找。也就是说,现在查表就行,不一层一层往上找了。

        每个类中都有一个虚方法表,表中存放着各个方法的实际入口。

2:虚方法表创建时机

        那么虚方法表什么时候被创建?虚方法表会在类加载的链接阶段被创建并开始初始化,类的变量初始值准备完成之后,JVM会把该类的方法表也初始化完毕。

        我们当时讲类加载过程中的链接这个阶段的时候,其中解析的部分讲的不是特别的透彻,因为这个回合我们后边也就是现在有一些想通的内容。解析阶段会将常量池中的符号应用转换为直接引用。这个符号就包括类的符号、方法的符号等等。

(一):例子一

        左右两侧是父类和子类在类中维护的两个虚方法表,表中蓝色部分二者都没重写,都继承自Object。子类中也直接把这些方法存到了虚方法表中,找的时候直接从索引表中可以找到Object的方法来使用需要通过父类在后在找到Object中去寻找方法。

        然后,二者都重写了hard开头的两个方法,所以箭头指向了他们自己。

(二):例子二

        继承关系图:

        Java代码编写:

interface Friendly{
    void sayHello();
    void sayGoodBye();
}

class Dog{
    public void sayHello(){
    }
    public String toString(){
        return "Dog";
    }
}

class Cat implements Friendly{
    public void eat(){
    }
    public void sayHello(){
    }
    public void sayGoodBye() {
    }
    public void finalize(){
    }
}

class CockerSpaniel extends Dog implements Friendly{
    public void sayHello() {
        super.sayHello();
    }
    public void sayGoodBye() {
    }
}
public class VirtualMethodTable {
}

         Dog虚方法表示意图:
 

        Dog这个虚方法表重写sayHello和toString,所以这两个方法指向自己,其他的虚方法指向父类。 虚方法就不需要一层一层向上判断了。

        CockerSpaniel示意图:

        Cat的示意图:

3:虚方法表出现意义

        他的出现是因为因为方法的重写,重写导致invokeVirtual寻找方法的时候一层一层向上找,会影响方法执行的效率,JVM基于虚方法表做了调整。简化寻找过程,提升效率。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity中结构体定义的成员如何显示在窗口中

在Unity中,有时候我们在处理数据的时候会用到结构体定义一些Unity组件相关的数据成员,并且需要在编辑器中拉取对象赋值。比如: using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;publ…

正则表达式(9):扩展正则表达式

正则表达式(9):扩展正则表达式 小结 本博文转载自 前文中一直在说,在Linux中,正则表达式可以分为”基本正则表达式”和”扩展正则表达式”。 我们已经认识了”基本正则表达式”,现在,我们来认…

笔记本电脑安装了Ubuntu系统设置关盖/合盖不挂起/不睡眠

文章目录 简介通过gnome-tweaks设置通过更改登录配置文件logind.conf设置参考资料 简介 学习工作中需要用到笔记本安装Ubuntu Linux系统,并且需要关盖电脑不关机、不挂起且不睡眠。为此,本篇博客整理了两种常规操作方式,并给了详细的步骤&am…

windows10安装MongoDB的入门简易教程【学习自用】

一、下载安装包 下载地址 https://www.mongodb.com/try/download/community 因为我是在windows上安装,所以下载windows版本的压缩包格式 二、下载后解压到要安装的目录里去 我这里在D盘装,所以就解压到D盘中我自己建的的mongoDB文件夹中。 三、在解…

网络安全攻击预警/态势预测算法汇总

总结: 网络安全攻击预警/态势预测算法众多,主要包括: 基于统计学的算法:协方差矩阵、马尔可夫模型等; 基于机器学习的算法:贝叶斯网络、聚类算法、支持向量机SVM、遗传算法、层次分析法AHP、决策树等&am…

LeetCode 每日一题 Day 10 || 并查集/二分搜索

1631. 最小体力消耗路径 你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights ,其中 heights[row][col] 表示格子 (row, col) 的高度。一开始你在最左上角的格子 (0, 0) ,且你希望去最右下角的格子 (rows-1, columns-1) (注…

案例056:基于微信小程序的购物系统

文末获取源码 开发语言:PHP 框架:Think PHP 数据库:mysql 5.7 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序运行软件:微信开发者工具 目录 前言 系统展示 后台模块的实现 用户信息管理 商品信…

USB Type-C一拖二线缆制作方法

1 实现方法 Figure 1-1 Type-C Socket(母口) Figure 1-2 Type-C Plug(公头) Table 1-1 Type-C Socket Pin连接描述 Type-C Plug连接, 需要做一个一拖二的线,一根的一端是USB, 另外一根的一端是USB转UART, 参考Table 1-2。 Table 1…

windows MYSQL解决中文乱码问题

1.首先确保你已经把mysql配置了环境变量 2.打开window终端 3.输入mysql -u root -p 4.输入密码,就是安装的时候设置的root超级管理员权限密码 5.输入: SHOW VARIABLES LIKE ‘character%’; 出现上图,说明就会出现中文乱码问题。 6.该怎么办…

31、卷积 - 参数 dilation 以及空洞卷积

在卷积算法中,还有一个不常见的参数叫做dilation(中文:膨胀)。 很多同学可能没听说过这个参数,下面看看这个参数有什么作用,用来控制什么的。 我们还是放这个经典的卷积运算图,图中是看不出 dilation 这个参数的存在的。 如果再换一张图呢,发现两图的区别了吗? 没错…

JavaDay17

创建不可变集合 import java.util.Iterator; import java.util.List;public class Test {public static void main(String[] args) {/*创建不可变的List集合* "张三" "李四" "王五" "赵六*///一旦创建之后 是无法进行修改的 在下面的代码…

[Linux] nginx防盗链与优化

一、Nginx的页面优化 1.1 Nginx的网页压缩 在Nginx的ngx_http_gzip_module压缩模块提供对文件内容压缩的功能。进行相关的配置修改,就能实现Nginx页面的压缩,达到节约带宽,提升用户访问速度 vim /usr/local/nginx/conf/nginx.conf http { .…

Shell三剑客:正则表达式简介

前言 一、名称解释 正则表达式(regular expression,RE)是一种字符模式,用于在查找过程中匹配指定的字符。在大多数程序里,正则表达式都被置于两个正斜杠之间;例如/l[oO]ve/就是由正斜杠界定的正则表达式&am…

python基于ModBusTCP服务端的业务实现特定的client

python实现ModBusTCP协议的client是一件简单的事情,只要通过pymodbus、pyModbusTCP等模块都可以实现,本文采用pymodbus。但要基于ModBusTCP服务端的业务实现特定的client,那得看看服务端是否复杂。前面系列文章,我们学习了对服务端…

无需公网IP联机Minecraft,我的世界服务器本地搭建教程

目录 前言 1.Mcsmanager安装 2.创建Minecraft服务器 3.本地测试联机 4. 内网穿透 4.1 安装cpolar内网穿透 4.2 创建隧道映射内网端口 5.远程联机测试 6. 配置固定远程联机端口地址 6.1 保留一个固定TCP地址 6.2 配置固定TCP地址 7. 使用固定公网地址远程联机 8.总…

开关量防抖滤波器(梯形图和SCL源代码)

模拟量防抖超限报警功能块请查看下面文章链接: https://rxxw-control.blog.csdn.net/article/details/133969425https://rxxw-control.blog.csdn.net/article/details/133969425 1、开关量防抖滤波器 2、防抖滤波 3、梯形图代码

【conda】利用Conda创建虚拟环境,Pytorch各版本安装教程(Ubuntu)

TOC conda 系列: 1. conda指令教程 2. 利用Conda创建虚拟环境,安装Pytorch各版本教程(Ubuntu) 1. 利用Conda创建虚拟环境 nolonolo:~/sun/SplaTAM$ conda create -n splatam python3.10查看结果: (splatam) nolonolo:~/sun/SplaTAM$ cond…

手把手教你玩转ESP8266(原理+驱动)

在嵌入式开发中,无线通信的方式有很多,其中 WIFI 是绕不开的话题。说到 WIFI 通信,就不得不提 ESP8266了。 ESP8266 是一款高性能的 WIFI 串口模块,实现透明传输。只要有一定的串口知识,不需要知道 WIFI 原理就可以上…

【Qt开发流程】之UI风格、预览及QPalette使用

概述 一个优秀的应用程序不仅要有实用的功能,还要有一个漂亮美腻的外观,这样才能使应用程序更加友善、操作性良好,更加符合人体工程学。作为一个跨平台的UI开发框架,Qt提供了强大而且灵活的界面外观设计机制,能够帮助…

如何快速访问未知世界【献给我的一位尚未谋面的“故友”】

1.下载Chrome浏览器 想要访问未知世界,强烈推荐Chrome,好用无广告,点击链接即可下载: 点我访问下载页面 2.安装插件 下一步,我们需要安装一个插件,这个插件能为Chrome浏览器插上腾飞的翅膀 [doge] (可以…