Search code examples
javajvmfinal

Handling of `final` by the 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.

My argument is that

  • For the security of the JVM is crucial that e.g. String is final, 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?


Solution

  • Yes, you're right.


    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 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.
    • […]

    (See there for many more details, including what the JVM is supposed to do when a class file violates this constraint.)


    For fields marked as final, see ibid., §§6.5–6 "putfield" and "putstatic", which say in part of 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.

    and likewise of putstatic, but with "the <clinit> method" instead of "an instance initialization method (<init>).

    (As you may have guessed, putfield and putstatic are the bytecode instructions for setting instance and static fields, respectively.)