Java 15 Hidden Classes Guide
Hidden classes are classes that cannot be used directly by the bytecode of other classes. They are intended for use by frameworks that generate classes at runtime and use them indirectly through reflection.
NOTE: Hidden classes are primarily used by frameworks and language runtimes. They are not typically used directly in application code.
- Cannot be linked by other classes: Hidden classes cannot be referenced directly in bytecode
- Not discoverable by reflection: Unless explicitly allowed, hidden classes are not visible via reflection
- Can be unloaded independently: Hidden classes can be garbage collected when not needed
- Created at runtime: Hidden classes are generated dynamically
- Not part of the package hierarchy: Hidden classes don't follow normal package structure
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
// Framework creates hidden class
MethodHandles.Lookup lookup = MethodHandles.lookup();
byte[] byteCode = generateClassBytecode();
Lookup.ClassOption[] options = {Lookup.ClassOption.NESTMATE};
Lookup hiddenLookup = lookup.defineHiddenClass(
byteCode,
true, // initialize class
options
);
Class<?> hiddenClass = hiddenLookup.lookupClass();
// Hidden class can be used via reflection or method handles
// But not directly referenced in bytecode-
Frameworks loading classes dynamically
- Dynamic proxy generation
- Runtime code generation
- Framework internals
-
Language runtimes
- Lambda expression implementation
- Dynamic method handles
- Scripting engines
-
Application servers
- Dynamic class loading
- Hot deployment
- Plugin systems
-
Dynamic code generation
- Code generators
- Template engines
- Compiler frameworks
-
Performance optimization
- Faster class loading
- Reduced memory footprint
- Better garbage collection
- Better encapsulation: Hidden classes are not visible to application code
- Can be unloaded when not needed: Improves memory management
- Faster class loading: Optimized for runtime generation
- Framework-friendly API: Designed for framework developers
- Reduced memory footprint: Can be garbage collected independently
// Framework generates bytecode for a proxy class
byte[] proxyBytecode = generateProxyClass(targetInterface);
// Create hidden class
Lookup lookup = MethodHandles.lookup();
Lookup hiddenLookup = lookup.defineHiddenClass(
proxyBytecode,
true
);
// Use hidden class via method handles
Class<?> proxyClass = hiddenLookup.lookupClass();
// Hidden class is not visible to other classes' bytecode
// But can be used via reflection or method handles- Framework-focused: Hidden classes are primarily for framework developers
- Not for application code: Not typically used directly in application code
- JVM internal use: Used internally by JVM for lambdas and other features
- Performance benefits: Can improve performance for dynamic class loading
- Better than anonymous classes: More efficient than anonymous classes for some use cases
Frameworks and systems that use hidden classes:
- Lambda expression implementation: JVM uses hidden classes for lambda expressions
- Dynamic proxy generation: Frameworks generate proxies as hidden classes
- Bytecode manipulation frameworks: ASM, Javassist, etc.
- Application servers: Dynamic class loading and hot deployment
- Scripting engines: Runtime code generation
- Visible to all classes in the same package
- Can be discovered via reflection
- Part of the package hierarchy
- Cannot be unloaded independently
- Slower class loading
Hidden Classes
- Not visible to other classes' bytecode
- Not discoverable by reflection (unless allowed)
- Not part of package hierarchy
- Can be unloaded independently
- Faster class loading
MethodHandles.Lookup.defineHiddenClass()
public Lookup defineHiddenClass(byte[] bytes, boolean initialize, ClassOption... options)Parameters:
bytes: Bytecode of the class to defineinitialize: Whether to initialize the class immediatelyoptions: Class options (e.g., NESTMATE, STRONG)
Returns:
- A
Lookupobject that can access the hidden class
The JVM uses hidden classes internally to implement lambda expressions efficiently. Each lambda is compiled to a hidden class.
Frameworks can generate proxy classes as hidden classes, making them invisible to application code but usable via interfaces.
Application servers can use hidden classes for hot deployment, allowing classes to be unloaded when new versions are deployed.
Frameworks that generate code at runtime can use hidden classes to avoid polluting the class namespace.
- Encapsulation: Better separation between framework and application code
- Memory Management: Can be unloaded when not needed
- Performance: Faster class loading and better GC behavior
- Flexibility: Framework-friendly API for dynamic class generation
- Security: Hidden classes are not accessible to untrusted code
- JEP 371: Hidden Classes
- Java API Documentation for
MethodHandles.Lookup - Project Loom documentation (uses hidden classes)
Hidden classes provide a mechanism for frameworks to generate classes at runtime that are not visible to application code. This feature is primarily for framework developers and language runtimes, enabling better encapsulation, performance, and memory management for dynamically generated classes.