由JVM处理`final` [英] Handling of `final` by the JVM
问题描述
在对此问题的评论中,我声称最终
在某些情况下必须得到JVM的尊重。已经询问最终
变量的安全出版物,因此处理静态最终成员。但是如何强制执行最终的类和方法并禁止覆盖最终字段呢?恕我直言,这可以而且必须在课程加载时完成。
In a comment to this question, I'm claiming that final
in some cases must be honored by the JVM. The safe publication of final
variables has been already asked and so was the handling of static final members. But what about enforcing classes and methods being final and forbidding overwriting of final fields? IMHO this can and must be done at class loading time.
我的论点是
- 对于JVM的安全性至关重要,例如
String
是final
,因此不得加载扩展它的手工制作的类。 - 同样适用于
公共最终
字段。虽然反射可以改变它们,但它会在运行时进行检查。因此,加载时必须拒绝重新分配最终字段的字节码。
- For the security of the JVM is crucial that e.g.
String
isfinal
, so a hand-crafted class extending it must not be loaded. - Similarly for
public final
fields. While reflection can change them, it's checked at runtime. Therefore a bytecode reassigning final fields must be rejected when loaded, too.
但是我找不到证据。我是对的吗?
But I couldn't find a proof. Am I right?
推荐答案
是的,你说得对。
对于标记为 final
的类,请参阅 Java虚拟机规范:Java SE 8版,§ 4.10验证 class
文件,部分说明:
For classes marked as final
, see The Java Virtual Machine Specification: Java SE 8 Edition, §4.10 "Verification of class
Files", which says in part:
[…] the Java虚拟机需要自行验证它尝试合并的
类
文件是否满足所需的约束。 Java虚拟机实现验证每个类文件是否满足链接时的必要约束(§5.4)。
[…] 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:
- 确保
final
类没有子类。 - […]
- Ensuring that
final
classes are not subclassed. - […]
(有关更多详细信息,请参阅此处,包括当 class
文件违反此约束时JVM应执行的操作。)
(See there for many more details, including what the JVM is supposed to do when a class
file violates this constraint.)
对于标记为 final
的字段,请参阅同上,§§ 6.5– 6 putfield
和 putstatic
,其中部分代表 putfield
:
For fields marked as final
, see ibid., §§6.5–6 "putfield
" and "putstatic
", which say in part of putfield
:
否则,如果字段为
final
,则必须在当前类,指令必须在实例初始化m中发生当前类的ethod(< init>
)。否则,抛出IllegalAccessError
。
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>
)。
and likewise of putstatic
, but with "the <clinit>
method" instead of "an instance initialization method (<init>
).
(您可能已经猜到了, putfield
和 putstatic
分别是用于设置实例和静态字段的字节码指令。)
(As you may have guessed, putfield
and putstatic
are the bytecode instructions for setting instance and static fields, respectively.)
这篇关于由JVM处理`final`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!