当前位置:   article > 正文

Java虚拟机(JVM)中符号引用(symbolic reference)和直接引用以及转化过程

Java虚拟机(JVM)中符号引用(symbolic reference)和直接引用以及转化过程

在Java虚拟机(JVM)中,符号引用(symbolic reference)和直接引用(direct reference)是两种不同的引用方式。了解这两种引用方式有助于更深入地理解Java的运行时机制,特别是类加载和方法调用的过程。

1. 符号引用 (Symbolic Reference)

符号引用是一种通过名称来引用目标的方式。符号引用在编译时生成,并存储在类文件的常量池中。常量池中的符号引用可以是以下几种:

  • 类或接口的全限定名(如:java/lang/String)。
  • 字段的名称和描述符(如:value:[C)。
  • 方法的名称和描述符(如:length:()I)。

2. 直接引用 (Direct Reference)

直接引用是指实际指向目标的内存地址或偏移量。这种引用方式在运行时由JVM解析符号引用后生成,指向具体的内存位置,便于快速访问。

3. 符号引用转化为直接引用的过程

在Java程序运行时,符号引用需要被解析成直接引用,这个过程称为解析(Resolution)。这个过程通常发生在类加载的链接阶段的解析步骤,或者在首次使用符号引用时(如首次访问某个字段或调用某个方法)。

具体步骤如下:

  1. 类加载阶段

    • 类加载器读取类文件并创建对应的类对象。
    • JVM在链接阶段处理类的常量池中的符号引用,将其解析为直接引用。
  2. 首次使用符号引用

    • 当程序首次访问某个字段、方法或类时,JVM会查找并验证该符号引用是否存在。
    • 一旦找到目标,JVM将符号引用转换为直接引用,并将其存储在常量池中,以便后续快速访问。

示例

假设有以下Java代码:

String str = "Hello, World!";
int length = str.length();
  • 1
  • 2

在上述过程中,str 是一个变量引用,它指向一个 String 对象。在Java中,变量引用可以理解为以下两种情况之一:

  1. 符号引用(Symbolic Reference):在编译时,str 变量是通过符号引用来表示的。它被存储在类文件的常量池中,作为符号引用的一部分。这种引用形式仅在编译时存在,用于标识变量的名称和类型。

  2. 直接引用(Direct Reference):在运行时,str 变量会变成一个实际的内存地址,指向堆内存中的 String 对象。这种引用形式在程序运行时存在,用于直接访问对象的实际内存位置。

3.1 编译阶段(符号引用)

在编译阶段,代码中的变量 str 是一个符号引用。编译器将 str 变量的名称和类型信息存储在类文件的常量池中。例如,常量池中会有类似这样的符号引用:

  • #1 = Fieldref #2.#3 // String str
  • #2 = Class #4 // CurrentClass
  • #3 = NameAndType #5:#6 // str:Ljava/lang/String;
  • #4 = Utf8 "CurrentClass"
  • #5 = Utf8 "str"
  • #6 = Utf8 "Ljava/lang/String;"
3.2运行时(直接引用)

在运行时,JVM加载类文件并分配内存,变量 str 将被初始化为指向实际的 String 对象。假设代码如下:

String str = "Hello, World!";
  • 1

在运行时,str 变量会成为一个直接引用,指向堆内存中存储的 "Hello, World!" 字符串对象。

3.4 具体过程
  1. 类加载和初始化:当类加载器加载包含 str 变量的类时,JVM会根据类文件中的常量池信息创建类对象,并在类加载时分配静态变量和实例变量的内存。
  2. 对象创建:在执行 String str = "Hello, World!"; 时,JVM会在堆内存中分配一个 String 对象,并初始化为 "Hello, World!"
  3. 变量引用str 变量会被赋值为指向这个 String 对象的内存地址。此时,str 是一个直接引用,指向堆内存中的字符串对象。

在Java中,变量 str 在编译时是符号引用,用于标识变量名称和类型。在运行时,str 变成一个直接引用,指向堆内存中的实际对象。通过这种方式,JVM能够高效地管理内存和访问对象。

同时在编译时,编译器会将对str.length()的调用记录为符号引用,存储在常量池中。在运行时,当JVM第一次解析str.length()时:
JVM会查找String类的length方法。
确认length方法的存在并加载对应的类。
将符号引用str.length()解析为直接引用,指向实际的length方法实现的内存地址。
后续对str.length()的调用将直接使用这个直接引用,避免再次解析符号引用。

4. 总结

符号引用转化为直接引用是Java虚拟机在运行时对程序代码进行优化的关键步骤。通过这种转换,JVM可以提高方法调用和字段访问的效率,从而提升Java程序的整体性能。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/779199
推荐阅读
相关标签
  

闽ICP备14008679号