Details
-
Sub-task
-
Resolution: Delivered
-
P4
-
15
-
Verified
Description
[JEP 371](https://openjdk.java.net/jeps/371) introduces hidden classes in Java 15. Hidden classes have the following implications to existing code:
1. `Class::getName` traditionally returns a binary name, but for a hidden class it returns a string that contains an ASCII forward slash (`/`) and is therefore not a binary name. Programs that assume the returned string is a binary name might need to be updated to handle hidden classes. That said, the longstanding practice of `Unsafe::defineAnonymousClass` was to define classes whose names were not binary names, so some programs may already handle such names successfully.
2. `Class::descriptorString` and `MethodType::descriptorString` returns a string that contains a ASCII dot (`.`) for a hidden class and therefore is not a type descriptor conforming to JVMS 4.3. Programs that assume the returned string is a type descriptor that conforms to JVMS 4.3 might need to be updated to handle hidden classes.
3. `Class::getNestMembers` is changed to not throw an exception when it fails to validate a nest membership of any member listed in `NestMembers` attribute. Instead, `Class::getNestMembers` returns the nest host and the members listed in the host's `NestMembers` attribute that are successfully resolved and determined to have the same nest host as this class. (This means it may return fewer members that listed in `NestMembers` attribute.) Existing code that expects `LinkageError` when there is a bad nest membership might be impacted.
4. The nestmate test in the JVM is changed to throw only `IllegalAccessError` when the nest membership is invalid. Some historical understanding is necessary:
- In Java 8, every access control failure was signaled with `IllegalAccessError` (IAE). Moreover, if a given access check failed with IAE once, then the same check would fail with IAE every time.
- In Java 11, the introduction of nest mates (JEP 181) meant that an access control failure could be signaled either with `IllegalAccessError` or, if nest membership was invalid, `LinkageError`. Still, if a given access check failed with a specific exception, then the same check would always fail with the same exception.
- In Java 15, the introduction of `Lookup::defineHiddenClass` implies that the nest host of the lookup class must be determined eagerly, when the hidden class is defined as a nestmate of the lookup class. Both `Lookup::defineHiddenClass` and `Class::getNestHost` both determine the nest host of a class in a more resilient manner than the JVM did in Java 11; namely, the API simply treats a class as self-hosted if its purported nest membership is invalid. For consistency with the API, the JVM no longer throws `LinkageError` when a class's nest membership is invalid, and instead treats the class as self-hosted. This means that the JVM only throws IAE from access control (because a self-hosted class will not permit any other class to access its private members). This is the behavior expected by the vast majority of user code.
5. JVM TI `GetClassSignature` returns a string that contains a ASCII dot (`.`) for a hidden class. JVM TI agents might need updating for hidden classes if they assume the returned string from `GetClassSignature` is a type descriptor conforming to JVMS 4.3.
1. `Class::getName` traditionally returns a binary name, but for a hidden class it returns a string that contains an ASCII forward slash (`/`) and is therefore not a binary name. Programs that assume the returned string is a binary name might need to be updated to handle hidden classes. That said, the longstanding practice of `Unsafe::defineAnonymousClass` was to define classes whose names were not binary names, so some programs may already handle such names successfully.
2. `Class::descriptorString` and `MethodType::descriptorString` returns a string that contains a ASCII dot (`.`) for a hidden class and therefore is not a type descriptor conforming to JVMS 4.3. Programs that assume the returned string is a type descriptor that conforms to JVMS 4.3 might need to be updated to handle hidden classes.
3. `Class::getNestMembers` is changed to not throw an exception when it fails to validate a nest membership of any member listed in `NestMembers` attribute. Instead, `Class::getNestMembers` returns the nest host and the members listed in the host's `NestMembers` attribute that are successfully resolved and determined to have the same nest host as this class. (This means it may return fewer members that listed in `NestMembers` attribute.) Existing code that expects `LinkageError` when there is a bad nest membership might be impacted.
4. The nestmate test in the JVM is changed to throw only `IllegalAccessError` when the nest membership is invalid. Some historical understanding is necessary:
- In Java 8, every access control failure was signaled with `IllegalAccessError` (IAE). Moreover, if a given access check failed with IAE once, then the same check would fail with IAE every time.
- In Java 11, the introduction of nest mates (JEP 181) meant that an access control failure could be signaled either with `IllegalAccessError` or, if nest membership was invalid, `LinkageError`. Still, if a given access check failed with a specific exception, then the same check would always fail with the same exception.
- In Java 15, the introduction of `Lookup::defineHiddenClass` implies that the nest host of the lookup class must be determined eagerly, when the hidden class is defined as a nestmate of the lookup class. Both `Lookup::defineHiddenClass` and `Class::getNestHost` both determine the nest host of a class in a more resilient manner than the JVM did in Java 11; namely, the API simply treats a class as self-hosted if its purported nest membership is invalid. For consistency with the API, the JVM no longer throws `LinkageError` when a class's nest membership is invalid, and instead treats the class as self-hosted. This means that the JVM only throws IAE from access control (because a self-hosted class will not permit any other class to access its private members). This is the behavior expected by the vast majority of user code.
5. JVM TI `GetClassSignature` returns a string that contains a ASCII dot (`.`) for a hidden class. JVM TI agents might need updating for hidden classes if they assume the returned string from `GetClassSignature` is a type descriptor conforming to JVMS 4.3.