当前位置: 首页 > news >正文

深入理解JVM虚拟机第二十四篇:详解JVM当中的动态链接和常量池的作用

大神链接:作者有幸结识技术大神孙哥为好友,获益匪浅。现在把孙哥视频分享给大家。

孙哥链接:孙哥个人主页
作者简介:一个颜值99分,只比孙哥差一点的程序员
本专栏简介:话不多说,让我们一起干翻JVM

本文章简介:话不多说,让我们讲清楚JVM当中与操作数栈相关的动态链接和常量池的作用

文章目录

知识回顾

1:栈帧中的结构图解

2:结构概念回顾 

一:动态链接

1:动态链接概念

2:编写代码证明

3:源代码的Javap

二:常量池

1:常量池的概念

2:说明


知识回顾

1:栈帧中的结构图解

2:结构概念回顾 

         栈帧中的几部分大致可以分为这几个:局部变量表,操作数栈,动态链接,方法返回地址,一些附加信息。

        局部变量表,操作数栈我们都已经详细的分析过了,接下来,我们该分享动态链接了。

        值得一提的是:方法返回地址,动态链接和一些附加信息在有一些地方被称为帧数据区。这个概念主要在一些教材上是这样提到的,我们也需要知道。

一:动态链接

1:动态链接概念

        动态链接又称为:执行运行时常量池的方法引用。

        每一个栈帧内部都包含一个指向运行时常量池中该栈帧所属方法的引用。包含这个引用的目的就是为了支持当前方法的代码能够实现动态链接(Dynamic Linking)。比如: invokedynamic指令

        在Java源文件被编译到字节码文件中时,所有的变量和方法引用都作为符号引用 (Symbolic Reference)保存在class文件的常量池里。比如:描述一个方法调用了另外的其他方法时,就是通过常量池中指向方法的符号引用来表示的,那么动态链接的作用就是为了将这些符号引用转换为调用方法的直接引用

        常量池就是我们的类被加载的时候所需要的信息,类、属性、方法的各种信息都会使用符号的形式声明出来,这是对类中各类数据的一个描述,而这个描述基于符号引用进行存储到了常量池这个区域。

        而在栈帧中的字节码区域,字节码指令后边跟着一堆符号,这些符号就是常量池中的符号索引。这样就是所谓的:执行运行时常量池的方法引用。

        常量池就是字节码整理后的那个区域,常量池当方法运行时会进入到方法区当中,此时的常量池就被称为运行时常量池。

        动态链接的作用就是为了将这些符号引用转换为调用方法的直接引用 

        这一有一个问题,为什么要通过动态链接这种方式,而不是直接通过将数据直接放到引用的位置形成直接引用呢? 

        我们这样做的目的是为了保证相同数据只有一份,不同地方使用只需要添加引用即可。节约空间。提升运行效率。

        为什么需要这个运行时常量池呢?运行时常量池就是把字节码中的常量池加载到了方法区中,没有这个运行时常量池也行,采用直接引用即可,但是这样就回到了上边的问题。

        所以为什么需要常量池呢?
        动态链接和常量池的作用,就是为了提供一些符号和常量,便于指令的识别。

2:编写代码证明

/*** @author Administrator*/
public class DynamicLInkingTest {int num = 10;public void methodA(){System.out.println("methodA().....");}public void methodB(){System.out.println("methodB().....");methodA();num++;}
}

3:源代码的Javap

        基于Javap对字节码进行整理,按照格式进行输出。

PS D:\code\study\hadoop\shit\target\classes> javap -v .\DynamicLInkingTest.class
Classfile /D:/code/study/hadoop/shit/target/classes/DynamicLInkingTest.classLast modified 2023年11月12日; size 678 bytesSHA-256 checksum acf0e245362759ceb374039c92493caf8913ff898697f7735b6ddedb262d2bd7Compiled from "DynamicLInkingTest.java"
public class DynamicLInkingTestminor version: 0major version: 52flags: (0x0021) ACC_PUBLIC, ACC_SUPERthis_class: #8                          // DynamicLInkingTestsuper_class: #9                         // java/lang/Objectinterfaces: 0, fields: 1, methods: 3, attributes: 1
Constant pool:#1 = Methodref          #9.#23         // java/lang/Object."<init>":()V#2 = Fieldref           #8.#24         // DynamicLInkingTest.num:I#3 = Fieldref           #25.#26        // java/lang/System.out:Ljava/io/PrintStream;#4 = String             #27            // methodA().....#5 = Methodref          #28.#29        // java/io/PrintStream.println:(Ljava/lang/String;)V#6 = String             #30            // methodB().....#7 = Methodref          #8.#31         // DynamicLInkingTest.methodA:()V#8 = Class              #32            // DynamicLInkingTest#9 = Class              #33            // java/lang/Object#10 = Utf8               num#11 = Utf8               I#12 = Utf8               <init>#13 = Utf8               ()V#14 = Utf8               Code#15 = Utf8               LineNumberTable#16 = Utf8               LocalVariableTable#17 = Utf8               this#18 = Utf8               LDynamicLInkingTest;#19 = Utf8               methodA#20 = Utf8               methodB#21 = Utf8               SourceFile#22 = Utf8               DynamicLInkingTest.java#23 = NameAndType        #12:#13        // "<init>":()V#24 = NameAndType        #10:#11        // num:I#25 = Class              #34            // java/lang/System#26 = NameAndType        #35:#36        // out:Ljava/io/PrintStream;#27 = Utf8               methodA().....#28 = Class              #37            // java/io/PrintStream#29 = NameAndType        #38:#39        // println:(Ljava/lang/String;)V#30 = Utf8               methodB().....#31 = NameAndType        #19:#13        // methodA:()V#32 = Utf8               DynamicLInkingTest#33 = Utf8               java/lang/Object#34 = Utf8               java/lang/System#35 = Utf8               out#36 = Utf8               Ljava/io/PrintStream;#37 = Utf8               java/io/PrintStream#38 = Utf8               println#39 = Utf8               (Ljava/lang/String;)V
{int num;descriptor: Iflags: (0x0000)public DynamicLInkingTest();descriptor: ()Vflags: (0x0001) ACC_PUBLICCode:stack=2, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: aload_05: bipush        107: putfield      #2                  // Field num:I10: returnLineNumberTable:line 4: 0line 6: 4LocalVariableTable:Start  Length  Slot  Name   Signature0      11     0  this   LDynamicLInkingTest;public void methodA();descriptor: ()Vflags: (0x0001) ACC_PUBLICCode:stack=2, locals=1, args_size=10: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc           #4                  // String methodA().....5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: returnLineNumberTable:line 9: 0line 10: 8LocalVariableTable:Start  Length  Slot  Name   Signature0       9     0  this   LDynamicLInkingTest;public void methodB();descriptor: ()Vflags: (0x0001) ACC_PUBLICCode:stack=3, locals=1, args_size=10: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc           #6                  // String methodB().....5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: aload_09: invokevirtual #7                  // Method methodA:()V12: aload_013: dup14: getfield      #2                  // Field num:I17: iconst_118: iadd19: putfield      #2                  // Field num:I22: returnLineNumberTable:line 13: 0line 15: 8line 17: 12line 18: 22LocalVariableTable:Start  Length  Slot  Name   Signature0      23     0  this   LDynamicLInkingTest;
}
SourceFile: "DynamicLInkingTest.java"

        我们关注一下methodB方法的内容:

        我们截取其中的一行的字节码指令,3是地址,或者应该叫偏移地址。ldc是具体的偏移地址下的字节码指令。

         3: ldc           #6                  // String methodB().....

二:常量池

1:常量池的概念

        常量池就是我们的类被加载的时候所需要的信息,类、属性、方法的各种信息都会使用符号的形式声明出来,#1=Methodref后边可能继续是符号引用或者是真实的数据。总之跟着符号索引一定可以找到最终的真实数据,这是对类中各类数据的一个描述,而这个描述基于符号引用进行处处到了常量池这个区域。

        而在栈帧中的字节码区域,字节码指令后边跟着一堆符号,这些符号就是常量池中的符号索引。这样就是所谓的:执行运行时常量池的方法引用。

Constant pool:#1 = Methodref          #9.#23         // java/lang/Object."<init>":()V#2 = Fieldref           #8.#24         // DynamicLInkingTest.num:I#3 = Fieldref           #25.#26        // java/lang/System.out:Ljava/io/PrintStream;#4 = String             #27            // methodA().....#5 = Methodref          #28.#29        // java/io/PrintStream.println:(Ljava/lang/String;)V#6 = String             #30            // methodB().....#7 = Methodref          #8.#31         // DynamicLInkingTest.methodA:()V#8 = Class              #32            // DynamicLInkingTest#9 = Class              #33            // java/lang/Object#10 = Utf8               num#11 = Utf8               I#12 = Utf8               <init>#13 = Utf8               ()V#14 = Utf8               Code#15 = Utf8               LineNumberTable#16 = Utf8               LocalVariableTable#17 = Utf8               this#18 = Utf8               LDynamicLInkingTest;#19 = Utf8               methodA#20 = Utf8               methodB#21 = Utf8               SourceFile#22 = Utf8               DynamicLInkingTest.java#23 = NameAndType        #12:#13        // "<init>":()V#24 = NameAndType        #10:#11        // num:I#25 = Class              #34            // java/lang/System#26 = NameAndType        #35:#36        // out:Ljava/io/PrintStream;#27 = Utf8               methodA().....#28 = Class              #37            // java/io/PrintStream#29 = NameAndType        #38:#39        // println:(Ljava/lang/String;)V#30 = Utf8               methodB().....#31 = NameAndType        #19:#13        // methodA:()V#32 = Utf8               DynamicLInkingTest#33 = Utf8               java/lang/Object#34 = Utf8               java/lang/System#35 = Utf8               out#36 = Utf8               Ljava/io/PrintStream;#37 = Utf8               java/io/PrintStream#38 = Utf8               println#39 = Utf8               (Ljava/lang/String;)V

2:说明

        当前我们只需要常量池对应了哪块区域即可,后边我们会详细的进行剖析。

相关文章:

深入理解JVM虚拟机第二十四篇:详解JVM当中的动态链接和常量池的作用

大神链接&#xff1a;作者有幸结识技术大神孙哥为好友&#xff0c;获益匪浅。现在把孙哥视频分享给大家。 孙哥链接&#xff1a;孙哥个人主页 作者简介&#xff1a;一个颜值99分&#xff0c;只比孙哥差一点的程序员 本专栏简介&#xff1a;话不多说&#xff0c;让我们一起干翻J…...

QGridLayout

QGridLayout QGridLayout 是 Qt 框架中的一个布局管理器类&#xff0c;用于在窗口或其他容器中创建基于网格的布局。 QGridLayout 将窗口或容器划分为行和列的网格&#xff0c;并将小部件放置在相应的单元格中。可以通过调整行、列和单元格的大小来控制布局的样式和结构。 以…...

万能在线预约小程序系统源码 适合任何行业在线预约小程序+预约到店模式 带完整的搭建教程

大家好啊&#xff0c;源码小编又来给大家分享啦&#xff01;随着互联网的发展和普及&#xff0c;越来越多的服务行业开始使用在线预约系统以方便客户和服务管理。例如&#xff0c;美发店、健身房、餐厅等都可以通过在线预约系统提高服务效率&#xff0c;减少等待时间&#xff0…...

Leetcode 2935. Maximum Strong Pair XOR II

Leetcode 2935. Maximum Strong Pair XOR II 1. 解题思路2. 代码实现 题目链接&#xff1a;2935. Maximum Strong Pair XOR II 1. 解题思路 这一题又是一个限制条件下找“最大值”的问题&#xff0c;不过这里的最大值是XOR之后的最大值。 而要求XOR之后结果的最大值&#x…...

[直播自学]-[汇川easy320]搞起来(4)看文档 查找设备(续)

2023.11.12 周六 19&#xff1a;05 补充一下关于以太网查找设备&#xff0c;如果设置如下&#xff1a; 然后点击测试&#xff1a; 点击ping 如果设置如下&#xff1a; 测试和ping和上图一样。 这就设计的有点不大好了&#xff01; 另…...

WebSphere Liberty 8.5.5.9 (四)

WebSphere Liberty 8.5.5.9 (四) [WebSphere Liberty 8.5.5.9]Linux 环境 ~$ unzip wlp-webProfile7-java8-linux-x86_64-8.5.5.9.zip ./ ~$ mkdir wlp-webProfile7-java8-8559 ~$ mv wlp ./wlp-webProfile7-java8-8559启动 WebSphere Liberty 8.5.5.9 服务 ~$ cd /home/tes…...

UE特效案例 —— 角色刀光

目录 一&#xff0c;环境配置 二&#xff0c;场景及相机设置 三&#xff0c;效果制作 刀光制作 地裂制作 击打地面炸开制作 一&#xff0c;环境配置 创建默认地形Landscape&#xff0c;如给地形上材质需确定比例&#xff1b;添加环境主光源DirectionalLight&#xff0c;设…...

11. EPIC定时器

11. EPIC定时器 EPIT定时器简介EPIT定时器结构分析EPIT 定时器相关寄存器EPITx_CREPITx_SREPITx_LR 加载寄存器EPITx_CMPR 比较寄存器EPITx_CNR 计数寄存器 EPIT 配置步骤 例程代码编写bsp_epittimer.hbsp_epittimer.cmain.c EPIT定时器简介 EPIT定时器是增强的周期中断定时器…...

git-bash配置代理

git-bash命令提交执行命令: "git push origin main"时发生错误: “$ git push origin main fatal: unable to access ‘https://github.com/satadriver/locust_server.git/’: Failed to connect to github.com port 443 after 21035 ms: Couldn’t connect to serve…...

【ElasticSearch系列-07】ES的开发场景和索引分片的设置及优化

ElasticSearch系列整体栏目 内容链接地址【一】ElasticSearch下载和安装https://zhenghuisheng.blog.csdn.net/article/details/129260827【二】ElasticSearch概念和基本操作https://blog.csdn.net/zhenghuishengq/article/details/134121631【三】ElasticSearch的高级查询Quer…...

JavaWeb Day09 Mybatis-基础操作02-XML映射文件动态SQL

目录 Mybatis动态SQL介绍​编辑 一、案例 ①Mapper层 ②测试类 ③EmpMapper.xml ④结果​ 二、标签 &#xff08;一&#xff09;if where标签 ​①EmpMapper.xml ②案例 ③总结 &#xff08;二&#xff09;foreach标签 ①SQL语句 ②Mapper层 ③EmpMapper.xml ④…...

CV学习基础

脸部检测是基于图像的明暗变化模式进行判断&#xff0c;需要将图像先进行灰度化处理 马赛克处理需先将图像缩小然后夸大回原尺寸。 保存训练好的算法用joblib 进行以下操作时已经使用cv2.cvtColor()完成了灰度化 图像平滑化&#xff08;模糊处理&#xff09;&#xff1a;cv…...

设计模式之禅之设计模式-原型模式

设计模式之禅之设计模式-原型模式 一&#xff1a;原型模式的定义 ​ 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 ​ 原型模式(Prototype Pattern)的简单程度仅次于单例模式和迭代器模式。正是由于简单,使用的场景才非常地多。 ​ 原型模式的核心是一…...

Spring的循环依赖问题

文章目录 1.什么是循环依赖2.代码演示3.分析问题4.问题解决5.Spring循环依赖6. 疑问点6.1 为什么需要三级缓存6.2 没有三级缓存能解决吗&#xff1f;6.3 三级缓存分别什么作用 1.什么是循环依赖 上图是循环依赖的三种情况&#xff0c;虽然方式有点不一样&#xff0c;但是循环依…...

RT-DETR算法改进:更换损失函数DIoU损失函数,提升RT-DETR检测精度

💡本篇内容:RT-DETR算法改进:更换损失函数DIoU损失函数 💡本博客 改进源代码改进 适用于 RT-DETR目标检测算法(ultralytics项目版本) 按步骤操作运行改进后的代码即可🚀🚀🚀 💡改进 RT-DETR 目标检测算法专属 文章目录 一、DIoU理论部分 + 最新 RT-DETR算法…...

【ICE】2:基于webrtc的 ice session设计及实现

工厂函数:CreateICESession_t 外部声明,sdk内部实现。创建IICESession :外部可见,内部也可见 /// Factory function prototype. How you get this factory will depend on how you are linking with /// this code. typedef IICESession *( *CreateICESession_t )( const…...

Vue组件传

跟禹神学vue--总结 1 父组件给子组件传递参数--props传参 &#xff08;1&#xff09;父组件中准备好数据 data() {return {todos:[{id:001,title:01,done:true},{id:002,title:02,done:false},{id:003,title:03,done:true}]} } &#xff08;2&#xff09;父组件中引入子组件…...

轻量封装WebGPU渲染系统示例<25>- 颜色附件数据更新替换(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/ColorAttachmentReplace.ts 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下: const rttTex0 { diffuse: { uuid: rtt0, rttTexture: {} } }; c…...

c语言练习第11周(1~5)

数列 1 1 2 3 5 8 13 21 ... 被称为斐波纳数列。 输入若干个正整数N&#xff0c;输出这个序列的前 N 项的和。 题干数列 1 1 2 3 5 8 13 21 ... 被称为斐波纳数列。 输入若干个正整数N&#xff0c;输出这个序列的前 N 项的和。输入样例3 5 4 1输出样例…...

阿里云国际站服务器如何升级内存容量?

阿里云服务器是阿里云供给的计算服务&#xff0c;它具有高效安稳、可扩展性强等特色&#xff0c;适用于各种应用环境。在运用阿里云服务器的过程中&#xff0c;或许会遇到内存容量缺乏的状况&#xff0c;这时候就需求晋级内存容量。那么&#xff0c;阿里云服务器怎么晋级内存容…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...