public final class HiddenClassDefiner
extends Object
Central facility for defining hidden classes (JEP 371).
MethodHandles.lookup is caller-sensitive: it returns a full-privilege lookup only for the class that literally contains the call. Production call sites capture a lookup on the intended nest host:
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
Class<?> hidden = HiddenClassDefiner.tryDefineNestmate(LOOKUP, bytecode, false);
Lookup#lookupClass()#lookupClass() fixes the hidden class's defining loader,
package, protection domain, and nest host. Lookups from different runtime
classes are not interchangeable as nest hosts even though they share the same
module rights (see below).
The lookup captured inside this class is used only as the caller argument to MethodHandles.privateLookupIn for the foreign-host overload — never as a production nest host.
Every production call site lives in the Groovy runtime, so lookup()
always grants the same module-level access. Capturing it in different runtime
classes does not open a third-party module that never opened itself to the
runtime. What differs is the nest host (package / loader / nest membership),
which still matters for unloadability and linkage.
With modules A (Java library), B (Groovy program), C (Groovy runtime):
privateLookupIn. Succeeds when the host package is open to the
runtime (typical for unnamed-module application classes); not for
strongly encapsulated packages such as java.lang
(String is the counter-example). Callers must handle
null and fall back to ClassLoader.defineClass.defineClass is the intentional safety net.
try* methods return null on expected failures
(IllegalAccessException, SecurityException, LinkageError,
invalid class-file / ASM exceptions, GraalVM UnsupportedFeatureError
matched by class name). Other Errors are rethrown.
isEnabled() is evaluated per call so
-Dgroovy.hidden.classes.disable=true works under native-image
build-time init, and is always false when
org.graalvm.nativeimage.imagecode=runtime.
| Modifiers | Name | Description |
|---|---|---|
static String |
PROPERTY_DISABLE |
System property that disables hidden-class definitions at run time. |
| Type Params | Return Type | Name and description |
|---|---|---|
|
public static boolean |
isEnabled()Whether hidden-class definition may be attempted in this process. |
|
public static Class<?> |
tryDefineNestmate(Lookup lookup, byte[] bytes, boolean initialize)Defines bytes as a hidden nestmate of lookup.lookupClass()
with a weak lifecycle. |
|
public static Class<?> |
tryDefineNestmate(Class<?> host, byte[] bytes, boolean initialize)Best-effort definition of a hidden nestmate of a foreign host. |
System property that disables hidden-class definitions at run time.
Whether hidden-class definition may be attempted in this process.
false when the kill switch is set or when running inside
a GraalVM native image at run time Defines bytes as a hidden nestmate of lookup.lookupClass()
with a weak lifecycle. The class-file package is rewritten to match the
lookup class before definition.
lookup - full-privilege lookup for the nest hostbytes - class-file bytesinitialize - true to run <clinit> immediatelynull if definition is not possible Best-effort definition of a hidden nestmate of a foreign host.
Uses privateLookupIn from this class; gated by
canAttemptPrivateLookup(Class). Not a substitute for a host-owned
lookup.
host - nest host and class-loader / package donorbytes - class-file bytesinitialize - true to run <clinit> immediatelynull if private lookup or definition fails