对此的评论question ,我声称在某些情况下 JVM 必须遵守 final
。 safe publication已经询问过 final
变量,handling of static final members 也是如此。 。但是强制类和方法为 Final 并禁止覆盖 Final 字段又如何呢?恕我直言,这可以而且必须在类加载时完成。
我的论点是
- 对于 JVM 的安全性至关重要,例如
String
是final
,因此不得加载扩展它的手工制作的类。 - 对于
public final
字段也是如此。虽然反射可以更改它们,但它会在运行时进行检查。因此,重新分配最终字段的字节码在加载时也必须被拒绝。
但我找不到证据。我说得对吗?
最佳答案
是的,你说得对。
对于标记为 final
的类,参见The Java Virtual Machine Specification: Java SE 8 Edition, §4.10 "Verification of class
Files" ,其中部分内容为:
[…] the Java Virtual Machine needs to verify for itself that the desired constraints are satisfied by the
class
files it attempts to incorporate. A Java Virtual Machine implementation verifies that each class file satisfies the necessary constraints at linking time (§5.4).[…]
[…] there are three additional checks outside the
Code
attribute which must be performed during verification:
- Ensuring that
final
classes are not subclassed.- […]
(请参阅此处了解更多详细信息,包括当 class
文件违反此约束时 JVM 应该执行的操作。)
对于标记为 final
的字段,参见ibid., §§6.5–6 " putfield
" and " putstatic
" ,其中部分内容为 putfield
:
Otherwise, if the field is
final
, it must be declared in the current class, and the instruction must occur in an instance initialization method (<init>
) of the current class. Otherwise, anIllegalAccessError
is thrown.
putstatic
同样如此,但使用“<clinit>
方法”而不是“实例初始化方法( <init>
)。
(正如您可能已经猜到的,putfield
和putstatic
分别是用于设置实例和静态字段的字节码指令。)
关于java - JVM 对 `final` 的处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30278780/