变量 'final' 修饰符丢失在字节码中?

Variable 'final' modifier lost in Bytecode?

分析这个简单 class 的字节码后,我得出的结论是编译器不会保留有关局部变量 final 的任何信息。这看起来很奇怪,因为我相信 HotSpot 编译器实际上可以使用这些信息来进行优化。

代码:

public static void main(String[] args)
{
    final int i = 10;
    System.out.println(i);
}

字节码:

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
  stack=2, locals=2, args_size=1
     0: bipush        10
     2: istore_1      
     3: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
     6: bipush        10
     8: invokevirtual #22                 // Method java/io/PrintStream.println:(I)V
    11: return        
  LineNumberTable:
    line 7: 0
    line 8: 3
    line 9: 11
  LocalVariableTable:
    Start  Length  Slot  Name   Signature
        0      12     0  args   [Ljava/lang/String;
        3       9     1     i   I

除了保存磁盘 space 之外,是否有任何特定原因 保留局部变量的访问标志?因为对我来说,似乎 final 是一个相对不平凡的 属性 变量。

字节码中没有 final 修饰符,但编译器已经使用此信息进行了一些优化。尽管您的示例没有显示,但编译器可能会在方法的字节码表示中内联 final 变量的值,从而提高性能。类似下面的内容可以显示差异:

public int addFinal() {
    final int i = 10;
    final int j = 10;
    return i + j;
}

public int addNonFinal() {
    int i = 10;
    int j = 10;
    return i + j;
}

每个方法生成的字节码分别为:

// addFinal
bipush 10
istore_1
bipush 10
istore_2
bipush 20
ireturn


// addNonFinal
bipush 10
istore_1
bipush 10
istore_2
iload_1
iload_2
iadd
ireturn