Mastering Java Hidden Classes: A Step-by-Step Guide with Code

This article explains Java hidden classes—runtime‑generated, reflection‑only classes—through a clear example that creates a simple class, encodes it, loads it as a hidden class, and invokes its method, demonstrating a powerful dynamic feature for frameworks.

Programmer DD
Programmer DD
Programmer DD
Mastering Java Hidden Classes: A Step-by-Step Guide with Code

What are Hidden Classes

Hidden classes are classes that cannot be accessed directly by other classes; they are intended for frameworks to generate and use at runtime via reflection.

Hidden Class Example

Step 1: Create a normal Java class.

public class JEP371HiddenClasses {
    public static String hello() {
        return "https://www.didispace.com";
    }
}

Step 2: Compile the class, read the .class file and encode it with Base64.

String filePath = "JEP371HiddenClasses.class";
byte[] b = Files.readAllBytes(Paths.get(filePath));
log.info(Base64.getEncoder().encodeToString(b));

The resulting Base64 string represents the compiled class.

Step 3: Load the hidden class via MethodHandles.defineHiddenClass and invoke its hello method.

@Test
void testHiddenClasses() throws Throwable {
    // 1. Load the encoded hidden class
    String CLASS_INFO = "yv66vgAAAD0AFAoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ+AQADKClWCAAIAQAZaHR0cHM6Ly93d3cuZGlkaXNwYWNlLmNvbQcACgEALmNvbS9kaWRpc3BhY2UvZGVidWcvamF2YTE1L0pFUDM3MUhpZGRlbkNsYXNzZXMBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAMExjb20vZGlkaXNwYWNlL2RlYnVnL2phdmExNS9KRVAzNzFIaWRkZW5DbGFzc2VzOwEABWhlbGxvAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAApTb3VyY2VGaWxlAQAYSkVQMzcxSGlkZGVuQ2xhc3Nlcy5qYXZhACEACQACAAAAAAACAAEABQAGAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAAAwANAAAADAABAAAABQAOAA8AAAAJABAAEQABAAsAAAAbAAEAAAAAAAMSB7AAAAABAAwAAAAGAAEAAAAGAAEAEgAAAAIAEw==";
    byte[] classInBytes = getDecoder().decode(CLASS_INFO);
    Class<?> proxy = MethodHandles.lookup()
        .defineHiddenClass(classInBytes, true, MethodHandles.Lookup.ClassOption.NESTMATE)
        .lookupClass();

    // Output class name and methods
    log.info(proxy.getName());
    for (Method method : proxy.getDeclaredMethods()) {
        log.info(method.getName());
    }

    // 2. Invoke hello()
    MethodHandle mh = MethodHandles.lookup().findStatic(proxy, "hello",
        MethodType.methodType(String.class));
    String result = (String) mh.invokeExact();
    log.info(result);
}

Running the test prints the hidden class name, its method name, and the string returned by hello():

17:20:50.360 [main] INFO com.didispace.debug.java15.JEP371Test - com.didispace.debug.java15.JEP371HiddenClasses/0x0000000800cb0c00
17:20:50.361 [main] INFO com.didispace.debug.java15.JEP371Test - hello
17:20:50.361 [main] INFO com.didispace.debug.java15.JEP371Test - https://www.didispace.com

This demonstrates how hidden classes provide an additional dynamic capability for framework developers.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaReflectionJDK 17Dynamic Class LoadingHidden ClassesJDK 15
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.