运行时常量池中数值存在的原因

public static final int CONST = 100; int y = CONST; 
0: bipush 100 

像这里,是直接使用100,还是需要用到常量池中100?
就是常量池中的100还有必要存在吗?已经写入了字节码指令中了

非常精准的问题!我们来深入拆一下字节码细节,看看这个 100 到底是不是还“依赖常量池”:


🔍 场景还原

public class Test {
    public static final int CONST = 100;
    public static void main(String[] args) {
        int y = CONST;
        System.out.println(y);
    }
}

javac 编译后:

javap -c -v Test

部分输出(简化):

Constant pool:
   #1 = Methodref          #6.#15         // java/lang/Object."<init>":()V
   #2 = Fieldref           #16.#17        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = Methodref          #18.#19        // java/io/PrintStream.println:(I)V
   #4 = Integer            100
   ...

Code:
   0: bipush        100
   2: istore_1
   3: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
   6: iload_1
   7: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V

🔑 分析

  1. bipush 100

    • bipush 是一个 JVM 指令,表示“直接将一个字节大小的常量压入操作数栈”。
    • 这里的 100 是直接写在字节码指令后的立即数(immediate operand),完全不依赖常量池
  2. 常量池的 #4 = Integer 100

    • 这是 .class 文件常量池中的一个 CONSTANT_Integer_info 表项。
    • 它保留了类中用到的字面量 100,即使生成了 bipush 100 指令,这个表项依然存在于常量池。
    • 但对于运行时执行 bipush 100JVM 根本不会去查常量池的 #4,它直接取字节码里的立即数。
  3. 为什么常量池还保留这个表项?

    • .class 文件的规范要求:源码中出现的字面量常量必须记录在常量池表中(即 Class 文件是“自描述”的)。
    • 编译器生成 bipush 时已经优化为直接数值,运行时不访问这个常量池表项。
    • 所以这个 #4 是“静态元信息”,主要用于类文件完整性和调试工具,不是执行时必需。

✅结论

  • 执行时:

    • bipush 100 指令直接把字节码里的立即数 100 压栈,不查常量池。
  • 常量池中的 Integer 100

    • 只是 .class 文件规范要求的字面量记录,对运行时这条指令没用。
    • 保留它是为了让 .class 文件完整、可反编译、可被其他工具读取。

📌一句话:

对于可以直接用 bipush/sipush/ldc 表达的常量,JVM 字节码直接携带立即数,执行时不依赖常量池表项;常量池里的数值更多是类文件元信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值