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();

在上述过程中,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!";

在运行时,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程序的整体性能。

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heromps

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值