java - JVM 对 `final` 的处理

标签 java jvm final

对此的评论question ,我声称在某些情况下 JVM 必须遵守 finalsafe publication已经询问过 final 变量,handling of static final members 也是如此。 。但是强制类和方法为 Final 并禁止覆盖 Final 字段又如何呢?恕我直言,这可以而且必须在类加载时完成。

我的论点是

  • 对于 JVM 的安全性至关重要,例如Stringfinal,因此不得加载扩展它的手工制作的类。
  • 对于 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, an IllegalAccessError is thrown.

putstatic 同样如此,但使用“<clinit> 方法”而不是“实例初始化方法( <init> )。

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

关于java - JVM 对 `final` 的处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30278780/

相关文章:

java - 使用 Jackson 将对象转换为 JSON 字符串

java - 使用Java在android中加载DXT纹理文件

java - 如何考虑夏令时在 mongoDB 中存储 future 的调度日期

java - 在单独的 JVM 上执行新的 JavaFX 应用程序

java - Switch 语句并在静态 block 中初始化最终静态变量

java - 在 java 中,如何在第 3 方工具返回的 DOM 中创建自己的 xml 子类元素

java - 当我在 Linux 或 Windows PC 上使用 Java 时。它使用哪个 JVM?是 j9 还是 JamVM 还是 Squeak?

java - 字符串实习如何在 Java 7+ 中工作?

java - 通过对象访问时静态最终字段和在声明时初始化的实例最终字段之间的差异

java - 是否可以在 Java 中扩展最终类?