JDK 15 Hidden ClassesOctober 16, 2020
Unlike sealed classes, hidden classes (JEP 371) are a JVM rather than a language-level feature. One of the specific goals of this feature is not to make any changes to the Java language.
Languages compiled into bytecodes, including Java, often use bytecodes that are generated at runtime, rather than fixing the implementation at compile time. An example of this is Lambda expressions, introduced in JDK 8. These represent the implementation of the single abstract method of a functional interface. Rather than restricting the compilation strategy to the simple use of an equivalent anonymous inner class, the compiler uses the invokedynamic bytecode, added to the JVM in JDK 7. At runtime, the JVM will generate a dynamic class that implements the functional interface and delivers the concrete implementation of the abstract method.
These dynamically created classes are mostly intended to be bound to the static class in which they are used. Although Lambda expressions can be assigned to a variable and reused, a very common use-case is within a stream. There is no need for the generated bytecode to be exposed outside the class where it is used. In this way, a dynamically generated class has three properties which are not possible to reflect in the existing class design accurately:
- Non-discoverability: Such classes do not need to be identified by a name so that they can be located by other classes.
- Access Control: The access control of the static class may need to be extended to include the dynamically generated one.
- Lifecycle: These dynamically generated classes may only be required for a short period compared to the lifetime of the static class that uses it. Memory usage can be reduced by decoupling the lifecycle of dynamic classes from the static class.
Some workarounds, such as per-class class loaders, have been used in the past, but these are not ideal.
The existing Lookup API is extended to support hidden classes that can only be accessed by reflection. A hidden class is not discoverable by the JVM during bytecode linkage, nor by programs making explicit use of class loaders. Hidden classes can be unloaded independently of the class that uses them. This allows them to be garbage collected in the usual way since there is no longer any references to them.
Used with permission and thanks, originally written as part of a longer article by Simon Ritter.