.class文件转换.java_Java中的动态链接VS操作系统动态链接

在操作系统OS中为了优化内存的使用会采用一种动态链接方式,一个文件想要在操作系统中运行必须经过编译、汇编译、链接、装载等步骤。可以参考Java程序是怎么跑起来的。本篇主要讲解Java栈帧中动态链接部分与操作系统的的动态链接的区别与联系

操纵系统为什么需要动态链接

OS是向下统一管理机器硬件、向上给各个应用程序提供统一的系统调用的程序。其中对内存的管理也是重头戏,以下是32位Linux操作系统中虚拟内存的空间分配图

1a390a9a2e5bd078b9b60e249a356316.png

每一个应用程序看到的内存就是这样的一段虚拟内存空间。应用程序的代码指令就存储在.text段也叫代码段,只读。.data段也叫数据段用于存储程序的静态变量、全局变量,可读可写

在应用程序的运行中除了运行自身的代码指令外还需要加载一些系统的公共库,比如用于网络收发的socket库等。在windows中,这些共享库以.dll(Dynamic-Link Libary 动态链接库)结尾,在Linux中以.so(Shared Object)结尾。加载这些共享库可进行对系统资源的调用

静态链接

当应用程序代码经历链接过程生成可执行文件时,每链接一个共享库就将共享库代码复制一份进应用程序的可执行文件中,因此有多少应用程序调用同一个共享库文件,该共享库文件中的代码就在内存中加载多少份

动态链接

在没用动态链接前,系统确实是采用静态链接的方式链接共享库,但是发现对内存的使用是一种极大的浪费,因此动态链接孕育而生。为了达到各个应用程序只加载同一个共享库但内存只存在一份共享库代码,动态链接首先解决的技术问题是地址无关性

PLT、GOT表解决地址无关性

我们都知道程序代码指令加载进内存的代码段是可执行只读的,无法动态的修改代码指令。那么当共享库载入内存中时是怎么被各个不同的应用程序找到的呢?

其实在应用程序的可执行文件加载进内存后,该程序的内存数据段(.data)存在一张GOT(Global Offset Table)全局偏移表,GOT表中,当有需要引用共享库地址的方法指令,都会查询 GOT,根据GOT表找到共享库方法指令的地址位置并调用。因为GOT存在于数据段,因此当共享库发生变化时,应用程序也不需要重新编译,可以直接动态的改变GOT表中的虚拟内存,从而找到最新的共享库。

共享库载入实际的物理内存,虽然物理内存不会变,但是每个应用程序看到的虚拟内存不一样,所以共享库在不同的应用程序中的虚存地址是不一样的,好在每个应用程序都拥有自己的GOT表,能够准确的记录了共享库的位置。这也就达到了地址无关性。

PLT(Procedure Link Table)程序链接表存在于内存的代码段中,主要是用于延迟绑定,我们可以将其理解为跳表。应用程序先是调用PLT表中查询需要调用的GOT表的地址位置,跳到GOT表后查询出共享库的虚存,然后再去调用共享库方法。因为很多动态装载的函数库都是不会被实际调用到的,而共享库中存在非常多的函数,因此采用PLT可达到延迟加载。

像动态链接这样通过修改“地址数据”来进行间接跳转,去调用一开始不能确定位置代码的思路,Java中的多态也采用了这种思想。

Java栈帧中的动态链接

以前的文章中解释了栈帧(拆解栈帧中本地变量表),其中动态链接也是组成栈帧的一部分。在上面对OS的解释中,动态链接是一种技术名称,在Java栈帧这里怎么就成了一个实体了呢?其实根据Java虚拟机对动态链接的描述,翻译成中文就是一个【引用】,那么栈帧存在的这个【引用】是干什么的呢?

在解释这个【引用】的作用之前,还是先说明一点,Java栈帧中的动态链接的目的其实跟OS的是一样的,都是为了节省内存空间,知道这个目的后我们再说明为什么可以节省。也因此在看JVM的时候,我总是会与OS做类比。

这个【引用】在虚机规范的解释为指向运行时常量池的方法引用。每当栈帧中调用其他方法时都会存在一个【引用】。在.class文件中所有的变量和方法引用都是符号引用(Symbolic Reference)也就是下面字节码中的 #数字。比如下面用javap反编译的.class文件中的Constant pool。

public class com.ethan.chapter02.Test02LocalVariablesminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPERConstant pool:
   #1 = Methodref          #7.#28         // java/lang/Object."":()V
   #2 = Class              #29            // com/ethan/chapter02/Test02LocalVariables
   #3 = Methodref          #2.#28         // com/ethan/chapter02/Test02LocalVariables."":()V
   #4 = Methodref          #2.#30         // com/ethan/chapter02/Test02LocalVariables.test3:()V
   #5 = Long               100l
   #7 = Class              #31            // java/lang/Object
   #8 = Utf8               
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               LocalVariableTable
  #13 = Utf8               this
  #14 = Utf8               Lcom/ethan/chapter02/Test02LocalVariables;
  #15 = Utf8               main
  #16 = Utf8               ([Ljava/lang/String;)V
  #17 = Utf8               args
  #18 = Utf8               [Ljava/lang/String;
  #19 = Utf8               variablesTable
  #20 = Utf8               num
  #21 = Utf8               I
  #22 = Utf8               test3
  #23 = Utf8               q
  #24 = Utf8               J
  #25 = Utf8               a
  #26 = Utf8               SourceFile
  #27 = Utf8               Test02LocalVariables.java
  #28 = NameAndType        #8:#9          // "":()V
  #29 = Utf8               com/ethan/chapter02/Test02LocalVariables
  #30 = NameAndType        #22:#9         // test3:()V
  #31 = Utf8               java/lang/Object
{public com.ethan.chapter02.Test02LocalVariables();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."":()V4: return
      LineNumberTable:
        line 10: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature0       5     0  this   Lcom/ethan/chapter02/Test02LocalVariables;public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=10: new           #2                  // class com/ethan/chapter02/Test02LocalVariables3: dup4: invokespecial #3                  // Method "":()V7: astore_18: bipush        1010: istore_211: aload_112: invokevirtual #4                  // Method test3:()V15: return
      LineNumberTable:
        line 12: 0
        line 13: 8
        line 14: 11
        line 15: 15
      LocalVariableTable:
        Start  Length  Slot  Name   Signature0      16     0  args   [Ljava/lang/String;8       8     1 variablesTable   Lcom/ethan/chapter02/Test02LocalVariables;11       5     2   num   Ipublic void test3();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=10: ldc2_w        #5                  // long 100l3: lstore_14: bipush        106: istore_37: return
      LineNumberTable:
        line 20: 0
        line 21: 4
        line 22: 7
      LocalVariableTable:
        Start  Length  Slot  Name   Signature0       8     0  this   Lcom/ethan/chapter02/Test02LocalVariables;4       4     1     q   J7       1     3     a   I
}

在.class文件中的常量池会随着文件被加载而转换进JVM中的运行时常量池中。由于存在了这些【符号引用】,可以使用Java层面的动态链接技术,将这些符号引用转换为调用方法的直接引用。比如字节码中的 invokevirtual指令就能够支持动态链接。

在类加载子系统中,一个.class文件被加载进JVM共需要经历3步骤,加载-链接-初始化。而在链接阶段中的第三步【解析】的目的就是将常量池内的符号引用转换为直接引用的过程,也就是动态链接产生的过程。

我们类比一下OS的动态链接与Java的动态链接。Java的.class文件类比于OS的每一个应用程序的可执行文件,.class文件中的常量池类比于GOT表,java的运行时常量池类比于共享库。java产生动态的链接是在.class的解析阶段,根据.class文件中的符号引用去查询常量池然后,将.class文件中的符号引用转换为直接应用,并存于栈帧中。

因为在加载不同的.class文件时,都可能调用相同的常量或者方法,所以只需要在运行时常量池存储一份,然后记录其直接引用即可,因此节省了空间。

解释完Java层面的动态链接我们也就能解释Java多态的实现过程了,在Java源代码编译期间方法的重写导致无法确认出调用方法的真正位置,只有在运行时将符号引用转为为直接应用采用确定方法的位置。这个过程也就是在【解析】阶段实现的。

这种编译时期无法确定方法的调用位置,只能够在程序运行期根据实际的类型绑定相关方法,这种绑定方式也就被称之为晚期绑定。

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

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

相关文章

宏观经济学gdp计算方法_宏观经济学考研的重要考点

宏观经济学考研重要考点西方国民收入核算宏观经济学的特点;国内生产总值;核算国民收入的两种算法(支出法和收入法);国内生产总值;个人可支配收入;国民收入的基本公式;名义GDP和实际GDP。要求:重点掌握本章基本概念及计算。简单国民收入决定理论均衡产出;凯恩斯的消费…

json符号解释大全_牛年汪姓男孩高端大气的名字大全

牛年汪姓男孩高端大气的名字大全 张桉宁起名分享牛年汪姓男孩高端大气的名字大全:给男孩起名有很多的讲究,需要从多个方面考虑。牛年汪姓男孩如何起一个高端大气的好名字,是家长朋友们都十分重视的。给牛年的汪姓男孩起一个高端的名字&#x…

变电站计算机在线监控系统,变电站环境在线监测系统

原标题:变电站环境在线监测系统概述随着计算机技术、网络通讯技术以及电力系统保护技术的发展,配电室的自动化运行水平不断提高,大大减少了人为操作,使配电室的无人值守逐步变成了可能。配电的可靠和安全是整个电能管理系统中的一…

什么意思是谁_舔狗是什么意思?如果不是真的喜欢谁又愿意做舔狗呢出处?

[海峡网]网络上面经常会出现一些新的词句,比如最近舔狗这个词就经常出现在大家的视线中。相信很多小伙伴都知道,最近关于虎牙的包子的事情也是挺多的,不过关于包桑的梗也是很多,那么关于包桑的这句“如果不是真的喜欢,…

计算机控制面板图标显示,Win8桌面如何有计算机/控制面板图标

Win8桌面如何有计算机/控制面板图标2013年06月04日 00:44作者:马承平编辑:马承平文章出处:泡泡网原创分享泡泡网系统工具频道6月4日 全新Windows8系统给我们带来不仅是超炫的动态磁贴展示,更有新增超级按钮项,它大大集…

计算机专业好还是铁道运输管理好,铁道运输管理专业主要是干什么的?

铁道运输管理专业主要是干什么的?铁道运输管理专业主要学什么?学铁道运营管理好就业吗?1、铁道交通运营管理专业主要培养德、智、体、美各方面全面发展,掌握所必需的基本理论和专业知识,有较高的综合素质和较强的铁道交通运营管理…

51单片机基本刷屏测试实验_51单片机开发基础8——实时时钟实验

8.1 实时时钟简介RTC(Real Time Clock),是实时时钟的缩写,实时时钟是日常生活中应用最为广泛的功能。它为人们提供精确的实时时间,或者为电子系统提供精确的时间基准,目前实时时钟芯片大多采用精度较高的晶体振荡器作为时钟源。有…

tensorflow超参数优化_机器学习模型的超参数优化

引言模型优化是机器学习算法实现中最困难的挑战之一。机器学习和深度学习理论的所有分支都致力于模型的优化。机器学习中的超参数优化旨在寻找使得机器学习算法在验证数据集上表现性能最佳的超参数。超参数与一般模型参数不同,超参数是在训练前提前设置的。举例来说…

南充一中计算机机房被盗,四川省CCF CSP-JS第一轮认证考试在南充一中成功举行...

10月11日,参加四川省青少年信息技术非专业级软件能力认证(CSP-JS)第一轮认证考试的来自遂宁市、南充市、达州市的220名参与认证的选手齐聚南充一中。软件能力认证(Certified Software Professional,简称CSP),是由中国计算机学会举办&#xff…

软件测试浏览器的上传功能,关于浏览器上传控件的识别 - asoqa的个人空间 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...

1:基本的上传控件(图1、图2)图1:MSN上传照片图2:ogame论坛上传图片这种基本的上传控件QTP脚本在处理时有两种方式:1.1 识别Windows选择框对象Dialog和WinListView,有点繁琐,但是能精确的定位用户操作。Brow…

串灯控制盒去掉怎么接_单双向可控硅好坏怎么判断

大功率可控硅好坏判断单向可控硅的工作原理: 可控硅导通条件:一是可控硅阳极与阴极间必须加正向电压,二是控制极也要加正向电压。以上两个条件 单向可控硅的工作原理图[1]必须同时具备,可控硅才会处于导通状…

江西小学计算机说课稿,2019江西教师招聘面试-小学数学-说课稿

教师招聘面试-小学数学-说课稿——《分数的基本性质》尊敬的各位考官大家好,我是今天的X号考生,今天我说课的题目是《分数的基本性质》新课标指出:数学课程要面向全体学生,适应学生个性发展的需要,使得人人都能获得良好…

无光驱如何修复W7计算机,Win7电脑没有光驱怎么装系统?

现在很多人买台式电脑不会再配置光驱了,可是这就让人有疑问了,如果没有光驱怎么装系统呢?其实方法很简单,我们可以用U盘,但是要想使用U盘必须先制作启动盘,如果你不懂怎么制作启动盘的话,那就赶…

云函数查询_速览 | 京东云5月重要产品与功能更新

新增产品高可用组 正式发布产品概述:高可用组是京东云提供的云主机逻辑集合,高可用组内的云主机分散部署在相互隔离的物理资源上,当出现硬件故障或定时维护时只会影响部分云主机,客户业务仍为可用状态,本服务免费。流水…

服务器文件夹同步到手机,本机文件夹同步到云服务器

本机文件夹同步到云服务器 内容精选换一换华为云帮助中心,为用户提供产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题、视频帮助等技术文档,帮助您快速上手使用华为云服务。本节操作介绍本地MacOS系统主机通过安装“Microsoft Rem…

centos7恢复mysql数据库_mysql数据库恢复过程记录

月初某晚朋友说数据库误删了,没有备份能不能恢复,我一愣,突然想到之前我们遇到过的问题,便问他是否开启了binlog。show variables like log_bin; //查看命令如果现实log_bin是ON,就说明打开了。值得庆幸,他…

绝地求生6月28日服务器维护,绝地求生6月28日更新到几点 吃鸡6月28日更新内容一览...

绝地求生6月28日更新到几点? 绝地求生6月28日更新内容一览。下面跟着小编一起来看看吧!绝地求生6.28维护时间上午10点开始(预计3个小时)下午1点开服绝地求生6月28日维护内容介绍通行证: 萨诺调整了通行证系统的机制- 每日最多获取XP 限制 80 改为120- 完成任务最少游戏时间&am…

in ms sql 集合参数传递_神奇的 SQL → 为什么 GROUP BY 之后不能直接引用原表中的列?...

GROUP BY 后 SELECT 列的限制标准 SQL 规定,在对表进行聚合查询的时候,只能在 SELECT 子句中写下面 3 种内容:通过 GROUP BY 子句指定的聚合键、聚合函数(SUM 、AVG 等)、常量。我们来看个例子:我们有 学生班级表(tbl_student_cla…

服务器日志文件中包含堆栈跟踪,日志框架 Logback 官方手册(第三章:Configuration)...

以下内容翻译整理自logback官方手册,地址:logback官方手册logback 配置将日志请求插入应用程序代码需要相当多的计划和工作。观察表明,大约有4%的代码用于日志记录。因此,即使是一个中等大小的应用程序,其代码中也会包…

extjs 月份选择控件_Excel | 做个生日提醒控件,本月或下月过生日的员工信息随你查看...

问题情境掌握职工的生日信息,及时送出生日祝福,是每位HR必备的技能。某公司要求将公司的员工生日信息实现查询,可方便的查看本月及下月过生日的员工信息,效果如下动图:效果中可以看出:勾选”本月生日“&…