Blocks :
|
|
CSR :
|
|
Relates :
|
|
Relates :
|
In principle, it is wrong for a class to extend a final class or to declare a method that overrides a final method in a superclass. JVM implementations have always respected this principle by refusing to load a class that attempts to do either of these things. Specifically, the longstanding behavior of HotSpot and J9 is to fail to define a class that either (i) extends a class whose ACC_FINAL flag is set, or (ii) declares a method that overrides a method whose ACC_FINAL flag is set. The failure occurs early enough in the class definition algorithm that no initiating loader is recorded for the given class name, and no `Class` object is exposed to user code. Unfortunately, the JVMS has always specified these checks to occur after class loading, as part of verification (JVMS 4.10). It would be undesirable for a JVM implementation to adhere to the JVMS by waiting until verification, because it would violate expected invariants about loaded classes. For example, it would expose programmers to `Class` objects that represent classes which extend final classes. (From a historical perspective, the discrepancy between the JVMS and JVM implementations is not surprising. The JVMS initially made no distinction between checking the format of a class file, verifying the code in a class file, and other class file validation actions -- they were all loosely considered "verification". There have since been multiple efforts to more precisely identify the timing and nature of such checks.) Besides the timing of the ACC_FINAL checks, there is the question of which exception to throw if the checks fail. Checking a class and its methods against ACC_FINAL flags in superclasses is fundamentally about detecting inconsistency _between_ classes. Such inconsistencies are usually signaled with IncompatibleClassChangeError, such as when a class's named superclass turns out to be an interface. Unfortunately, JVM implementations have always thrown VerifyError when they detect an ACC_FINAL violation. This should be changed, reserving VerifyError for actual failures of verification. Proposal: (1) Align the JVMS with JVM implementations by specifying that ACC_FINAL checks occur during class definition (JVMS 5.3.5), at the same time as other properties of the superclass are checked. (2) Specify that an IncompatibleClassChangeError occurs if the checks fail, modifying HotSpot to throw that instead of VerifyError (JDK-8243583). This makes the JVMS 4.10 rules about ACC_FINAL redundant, because verification will never encounter a class that extends a final class. Cleaning up the verification spec is left as a separate task (JDK-8258138).
|