aboutsummaryrefslogtreecommitdiffstats
path: root/tests/features197/java15/HiddenClassDemo.java
blob: 0b7f0ab176ab306d278ebd50f0cb2d00a6e0efb6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;

import java.io.FileInputStream;

import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;

public class HiddenClassDemo {
  public static void main(String[] args) throws Throwable {
    // Step 1: Create lookup object
    MethodHandles.Lookup lookup = MethodHandles.lookup();

    // Step 2: Fetch or create the class bytes we want to define
    byte[] bytes = Thread.currentThread().getContextClassLoader()
      .getResourceAsStream("HiddenClass.class")
      .readAllBytes();

    // Step 3: Define hidden class
    Class<?> clazz = lookup.defineHiddenClass(bytes, true, NESTMATE).lookupClass();
    // Hidden classes have class names like my.package.MyClass/0x2a23f5, but no canonical name (null)
    System.out.println("Hidden class name = " + clazz.getName());
    System.out.println("Hidden class canonical name = " + clazz.getCanonicalName ());
    // Hidden classes cannot be resolved by any class loader (ClassNotFoundException)
    try {
      Class.forName(clazz.getName());
    }
    catch (ClassNotFoundException e) {
      System.out.println("Class.forName resolution error = " + e);
    }

    //Step 4: Create instance of hidden class object and call interface method
    Test test = (Test) clazz.getConstructor(null).newInstance(null);
    test.concat("Hello", "from", "dynamically", "defined", "hidden", "class");
  }
}

interface Test {
  void concat(String... words);
}