.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,一经查实,立即删除!

相关文章

计算机组成原理与应用,计算机组成原理简答与应用

简答与应用1.何谓中断??中断是由外围设备或其他非预期的急需处理的事件引起的,CPU暂时中断正在执行的程序,转至另一服务程序去处理这一事件,待事件处理完毕后返回原程序继续执行。2.(不算CPU中的寄存器级)存…

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

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

大学计算机基础试题 选择题,大学计算机基础试题选择题

大学计算机基础试题选择题第一章1. 世界上第一台全自动电子数字计算机ENIAC的诞生时间是( )A. 1945年 B. 1946年 C. 1948年 D. 1949年2. 第一位提出“存储程序”思想的科学家是( )A. 图灵 B. 莱布尼茨 C. 冯诺伊曼 D. 帕斯卡3. 电子计算机四个发展阶段的划分依据是( )不同A. 电…

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

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

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

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

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

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

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

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

【Android 13】使用Android Studio调试系统应用之Settings移植(二):构建settings app项目目录

文章目录 一、篇头二、系列文章2.1 Android 13 系列文章2.2 Android 9 系列文章2.3 Android 11 系列文章三、准备工作3.1 创建目录3.2 初始化 git 仓库四、提取settings原始代码4.1 提取目标4.2 源码路径4.2.1 settings app4.2.2 SettingsLib4.3 存放位置

dog log 算子_DoG和LoG算子

DoG(Difference of Gaussian)算子和LoG(Laplacian of Gaussian)算子是常用的极值点检测(Blob Detection)两种方法,高斯卷积是为了进行尺度变换,那么LapLacian呢。 因此这里首先引入LapLacian算子。图像边缘检测因此进行边缘检测有两种方法。一阶导数的极…

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

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

大学期末考java编程题_大学java期末考试考试题和答案

题号一二三总分得分得分评卷人一、简单编程题<共50分)在考试文件夹中新建一个应用程序proj1<应用程序的文件夹名称为proj1)&#xff0c;按照以下要求编写程序代码。b5E2RGbCAP1.在程序中定义Person类&#xff0c;为该类编写如下字段、构造器、访问器、修改器和相应的其他…

计算机一级办公软件选择题,计算机一级MSOffice习题

2018年计算机等级考试即将开始&#xff0c;出国留学网为考生们整理了2018年计算机一级MSOffice习题答案&#xff0c;希望能帮到大家&#xff0c;想了解更多资讯&#xff0c;请关注小编的及时更新哦。2018年计算机一级MSOffice习题答案(7)第1章 计算机基础知识1.3 多媒体简介1[…

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

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

湖南省普通高等学校计算机应用水平,湖南省普通高等学校非计算机专业学生计算机应用水平二级考试大纲...

湖南省普通高等学校非计算机专业学生计算机应用水平二级考试大纲考试要求:1.掌握计算机的基础知识和网络知识2.正确理解微机及其操作系统的基本功能&#xff0c;熟练掌握常用操作系统的使用3.具有使用微机系统常用应用软件的基本能力4.掌握使用计算机网络获娶传输、发布信息的基…

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

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

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

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

java游戏猿人时代_猿人时代增值版_JAVA游戏免费版下载_7723手机游戏[www.7723.cn]

快速搜索机型:诺基亚 N70系列(176208)7610 3230 6600 6260 6620 6630 6670 6680 6681 6682 N70 N72 ;松下: X700 X800 ;联想: P930诺基亚 N73系列(240320)N73 5320 5320XM 5320di_XM 5630XM 5700 5700XM 5710XM 5730XM 6110 6110N 6120 6120C 6120ci 6121 6122C 6124C 6210S 62…

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

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

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

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

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

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