由JVM处理`final`

在对这个问题的评论中,我声称在某些情况下final必须得到JVM的尊重。 已经提出了final变量的安全发布 , 静态最终成员的处理也是如此。 但是如何强制执行最终的类和方法并禁止覆盖最终字段呢? 恕我直言,这可以而且必须在上课时间完成。

我的论点是

  • 因为JVM的安全性至关重要,例如Stringfinal ,所以不得加载扩展它的手工制作的类。
  • 同样适用于public final字段。 虽然reflection可以改变它们,但它会在运行时进行检查。 因此,加载时必须拒绝重新分配最终字段的字节码。

但我找不到证据。 我对吗?

你是对的。


对于标记为final类,请参阅Java虚拟机规范:Java SE 8 Edition ,§4.10“ class文件validation” ,其中部分说明:

[…] Java虚拟机需要自己validation它尝试合并的class文件是否满足所需的约束。 Java虚拟机实现validation每个类文件是否满足链接时的必要约束(第5.4节 )。

[…]

[…]在Code属性之外还有三个额外的检查,必须在validation期间执行:

  • 确保final类不是子类。
  • […]

(有关更多详细信息,请参阅此处,包括当class文件违反此约束时JVM应执行的操作。)


对于标记为final字段,请参阅同上,§§6.5-6“ putfield ”和“ putstatic ” ,其中部分为putfield

否则,如果该字段是final ,则必须在当前类中声明,并且该指令必须在当前类的实例初始化方法( )中进行。 否则, IllegalAccessError

同样也是putstatic ,但是用“ 方法”代替“实例初始化方法( )。

(正如您可能已经猜到的那样, putfieldputstatic分别是用于设置实例和静态字段的字节码指令。)