8256867: Classes with empty PermittedSubclasses attribute cannot be extended

Reviewed-by: lfoltan, mchung, jlahoda, chegar
This commit is contained in:
Harold Seigel 2020-12-09 19:07:11 +00:00
parent e6b4c4d716
commit d33a689b96
8 changed files with 154 additions and 61 deletions

View file

@ -4390,10 +4390,13 @@ public final class Class<T> implements java.io.Serializable,
*
* Returns an array containing {@code Class} objects representing the
* direct subinterfaces or subclasses permitted to extend or
* implement this class or interface if it is sealed. The order of such elements
* is unspecified. If this {@code Class} object represents a primitive type,
* implement this class or interface if it is sealed. The order of such elements
* is unspecified. The array is empty if this sealed class or interface has no
* permitted subclass. If this {@code Class} object represents a primitive type,
* {@code void}, an array type, or a class or interface that is not sealed,
* an empty array is returned.
* that is {@link #isSealed()} returns {@code false}, then this method returns {@code null}.
* Conversely, if {@link #isSealed()} returns {@code true}, then this method
* returns a non-null value.
*
* For each class or interface {@code C} which is recorded as a permitted
* direct subinterface or subclass of this class or interface,
@ -4406,7 +4409,8 @@ public final class Class<T> implements java.io.Serializable,
* cannot be obtained, it is silently ignored, and not included in the result
* array.
*
* @return an array of {@code Class} objects of the permitted subclasses of this class or interface
* @return an array of {@code Class} objects of the permitted subclasses of this class or interface,
* or {@code null} if this class or interface is not sealed.
*
* @throws SecurityException
* If a security manager, <i>s</i>, is present and the caller's
@ -4423,8 +4427,8 @@ public final class Class<T> implements java.io.Serializable,
@CallerSensitive
public Class<?>[] getPermittedSubclasses() {
Class<?>[] subClasses;
if (isArray() || isPrimitive() || (subClasses = getPermittedSubclasses0()).length == 0) {
return EMPTY_CLASS_ARRAY;
if (isArray() || isPrimitive() || (subClasses = getPermittedSubclasses0()) == null) {
return null;
}
if (subClasses.length > 0) {
if (Arrays.stream(subClasses).anyMatch(c -> !isDirectSubType(c))) {
@ -4469,7 +4473,9 @@ public final class Class<T> implements java.io.Serializable,
* Returns {@code true} if and only if this {@code Class} object represents
* a sealed class or interface. If this {@code Class} object represents a
* primitive type, {@code void}, or an array type, this method returns
* {@code false}.
* {@code false}. A sealed class or interface has (possibly zero) permitted
* subclasses; {@link #getPermittedSubclasses()} returns a non-null but
* possibly empty value for a sealed class or interface.
*
* @return {@code true} if and only if this {@code Class} object represents a sealed class or interface.
*
@ -4483,7 +4489,7 @@ public final class Class<T> implements java.io.Serializable,
if (isArray() || isPrimitive()) {
return false;
}
return getPermittedSubclasses().length != 0;
return getPermittedSubclasses() != null;
}
private native Class<?>[] getPermittedSubclasses0();