# HG changeset patch # User vromero # Date 1544715309 18000 # Node ID 4ddd3c410a85bfb7dc44e14f4ebd5f55eb41532f # Parent 8bf9268df0e2e7b8aa5dfabfa2efd1755b508381 8215300: additional changes to constants API Reviewed-by: goetz diff -r 8bf9268df0e2 -r 4ddd3c410a85 src/java.base/share/classes/java/lang/Double.java --- a/src/java.base/share/classes/java/lang/Double.java Thu Dec 13 15:31:05 2018 +0100 +++ b/src/java.base/share/classes/java/lang/Double.java Thu Dec 13 10:35:09 2018 -0500 @@ -1077,8 +1077,8 @@ } /** - * Returns a nominal descriptor for this instance, which is the instance - * itself. + * Returns an {@link Optional} containing the nominal descriptor for this + * instance, which is the instance itself. * * @return an {@link Optional} describing the {@linkplain Double} instance * @since 12 diff -r 8bf9268df0e2 -r 4ddd3c410a85 src/java.base/share/classes/java/lang/Float.java --- a/src/java.base/share/classes/java/lang/Float.java Thu Dec 13 15:31:05 2018 +0100 +++ b/src/java.base/share/classes/java/lang/Float.java Thu Dec 13 10:35:09 2018 -0500 @@ -989,8 +989,8 @@ } /** - * Returns a nominal descriptor for this instance, which is the instance - * itself. + * Returns an {@link Optional} containing the nominal descriptor for this + * instance, which is the instance itself. * * @return an {@link Optional} describing the {@linkplain Float} instance * @since 12 diff -r 8bf9268df0e2 -r 4ddd3c410a85 src/java.base/share/classes/java/lang/Integer.java --- a/src/java.base/share/classes/java/lang/Integer.java Thu Dec 13 15:31:05 2018 +0100 +++ b/src/java.base/share/classes/java/lang/Integer.java Thu Dec 13 10:35:09 2018 -0500 @@ -1838,8 +1838,8 @@ } /** - * Returns a nominal descriptor for this instance, which is the instance - * itself. + * Returns an {@link Optional} containing the nominal descriptor for this + * instance, which is the instance itself. * * @return an {@link Optional} describing the {@linkplain Integer} instance * @since 12 diff -r 8bf9268df0e2 -r 4ddd3c410a85 src/java.base/share/classes/java/lang/Long.java --- a/src/java.base/share/classes/java/lang/Long.java Thu Dec 13 15:31:05 2018 +0100 +++ b/src/java.base/share/classes/java/lang/Long.java Thu Dec 13 10:35:09 2018 -0500 @@ -1967,8 +1967,8 @@ } /** - * Returns a nominal descriptor for this instance, which is the instance - * itself. + * Returns an {@link Optional} containing the nominal descriptor for this + * instance, which is the instance itself. * * @return an {@link Optional} describing the {@linkplain Long} instance * @since 12 diff -r 8bf9268df0e2 -r 4ddd3c410a85 src/java.base/share/classes/java/lang/String.java --- a/src/java.base/share/classes/java/lang/String.java Thu Dec 13 15:31:05 2018 +0100 +++ b/src/java.base/share/classes/java/lang/String.java Thu Dec 13 10:35:09 2018 -0500 @@ -3545,8 +3545,8 @@ } /** - * Returns a nominal descriptor for this instance, which is the instance - * itself. + * Returns an {@link Optional} containing the nominal descriptor for this + * instance, which is the instance itself. * * @return an {@link Optional} describing the {@linkplain String} instance * @since 12 diff -r 8bf9268df0e2 -r 4ddd3c410a85 src/java.base/share/classes/java/lang/constant/ClassDesc.java --- a/src/java.base/share/classes/java/lang/constant/ClassDesc.java Thu Dec 13 15:31:05 2018 +0100 +++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.java Thu Dec 13 10:35:09 2018 -0500 @@ -112,13 +112,13 @@ * * A field type descriptor string for a non-array type is either * a one-letter code corresponding to a primitive type - * ({@code J,I,C,S,B,D,F,Z,V}), or the letter {@code L}, followed - * by the fully qualified binary name of a class, followed by {@code ;}. - * A field type descriptor for an array type is the character {@code [} + * ({@code "J", "I", "C", "S", "B", "D", "F", "Z", "V"}), or the letter {@code "L"}, followed + * by the fully qualified binary name of a class, followed by {@code ";"}. + * A field type descriptor for an array type is the character {@code "["} * followed by the field descriptor for the component type. Examples of - * valid type descriptor strings include {@code Ljava/lang/String;}, {@code I}, - * {@code [I}, {@code V}, {@code [Ljava/lang/String;}, etc. - * for more detail. + * valid type descriptor strings include {@code "Ljava/lang/String;"}, {@code "I"}, + * {@code "[I"}, {@code "V"}, {@code "[Ljava/lang/String;"}, etc. + * See JVMS 4.3.2 ("Field Descriptors") for more detail. * * @param descriptor a field descriptor string * @return a {@linkplain ClassDesc} describing the desired class @@ -126,9 +126,15 @@ * @throws IllegalArgumentException if the name string is not in the * correct format * @jvms 4.3.2 Field Descriptors + * @jvms 4.4.1 The CONSTANT_Class_info Structure */ static ClassDesc ofDescriptor(String descriptor) { requireNonNull(descriptor); + int depth = ConstantUtils.arrayDepth(descriptor); + if (depth > ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS) { + throw new IllegalArgumentException(String.format("Cannot create an array type descriptor with more than %d dimensions", + ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS)); + } return (descriptor.length() == 1) ? new PrimitiveClassDescImpl(descriptor) : new ReferenceClassDescImpl(descriptor); @@ -139,8 +145,15 @@ * is described by this {@linkplain ClassDesc}. * * @return a {@linkplain ClassDesc} describing the array type + * @throws IllegalStateException if the resulting {@linkplain ClassDesc} would have an array rank of greater than 255 + * @jvms 4.4.1 The CONSTANT_Class_info Structure */ default ClassDesc arrayType() { + int depth = ConstantUtils.arrayDepth(descriptorString()); + if (depth >= ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS) { + throw new IllegalStateException(String.format("Cannot create an array type descriptor with more than %d dimensions", + ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS)); + } return arrayType(1); } @@ -150,11 +163,14 @@ * * @param rank the rank of the array * @return a {@linkplain ClassDesc} describing the array type - * @throws IllegalArgumentException if the rank is zero or negative + * @throws IllegalArgumentException if the rank is less than zero or if the rank of the resulting array type is + * greater than 255 + * @jvms 4.4.1 The CONSTANT_Class_info Structure */ default ClassDesc arrayType(int rank) { - if (rank <= 0) - throw new IllegalArgumentException("rank: " + rank); + int currentDepth = ConstantUtils.arrayDepth(descriptorString()); + if (rank <= 0 || currentDepth + rank > ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS) + throw new IllegalArgumentException("rank: " + currentDepth + rank); return ClassDesc.ofDescriptor("[".repeat(rank) + descriptorString()); } @@ -162,6 +178,12 @@ * Returns a {@linkplain ClassDesc} for a nested class of the class or * interface type described by this {@linkplain ClassDesc}. * + * @apiNote + * + * Example: If descriptor {@code d} describes the class {@code java.util.Map}, a + * descriptor for the class {@code java.util.Map.Entry} could be obtained + * by {@code d.nested("Entry")}. + * * @param nestedName the unqualified name of the nested class * @return a {@linkplain ClassDesc} describing the nested class * @throws NullPointerException if any argument is {@code null} diff -r 8bf9268df0e2 -r 4ddd3c410a85 src/java.base/share/classes/java/lang/constant/Constable.java --- a/src/java.base/share/classes/java/lang/constant/Constable.java Thu Dec 13 15:31:05 2018 +0100 +++ b/src/java.base/share/classes/java/lang/constant/Constable.java Thu Dec 13 10:35:09 2018 -0500 @@ -65,8 +65,9 @@ */ public interface Constable { /** - * Returns a nominal descriptor for this instance, if one can be - * constructed, or an empty {@link Optional} if one cannot be constructed. + * Returns an {@link Optional} containing the nominal descriptor for this + * instance, if one can be constructed, or an empty {@link Optional} + * if one cannot be constructed. * * @return An {@link Optional} containing the resulting nominal descriptor, * or an empty {@link Optional} if one cannot be constructed. diff -r 8bf9268df0e2 -r 4ddd3c410a85 src/java.base/share/classes/java/lang/constant/ConstantUtils.java --- a/src/java.base/share/classes/java/lang/constant/ConstantUtils.java Thu Dec 13 15:31:05 2018 +0100 +++ b/src/java.base/share/classes/java/lang/constant/ConstantUtils.java Thu Dec 13 10:35:09 2018 -0500 @@ -37,6 +37,7 @@ /** an empty constant descriptor */ public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[0]; static final Constable[] EMPTY_CONSTABLE = new Constable[0]; + static final int MAX_ARRAY_TYPE_DESC_DIMENSIONS = 255; private static final Set pointyNames = Set.of("", ""); diff -r 8bf9268df0e2 -r 4ddd3c410a85 src/java.base/share/classes/java/lang/constant/package-info.java --- a/src/java.base/share/classes/java/lang/constant/package-info.java Thu Dec 13 15:31:05 2018 +0100 +++ b/src/java.base/share/classes/java/lang/constant/package-info.java Thu Dec 13 10:35:09 2018 -0500 @@ -49,7 +49,7 @@ * storing the value in a constant pool entry, or reconstituting the value given * a class loading context. Every {@link java.lang.constant.ConstantDesc} * knows how to resolve itself -- compute the value that it describes -- - * via {@link java.lang.constant.ConstantDesc#resolveConstantDesc(java.lang.invoke.MethodHandles.Lookup)}. + * via {@link java.lang.constant.ConstantDesc#resolveConstantDesc(java.lang.invoke.MethodHandles.Lookup) ConstantDesc.resolveConstantDesc}. * This allows an API which accepts {@link java.lang.constant.ConstantDesc} * objects to evaluate them reflectively, provided that the classes and methods * referenced in their nominal description are present and accessible. @@ -68,7 +68,7 @@ * When a bytecode-reading API encounters a constant pool entry, it can * convert it to the appropriate type of nominal descriptor. For dynamic * constants, bytecode-reading APIs may wish to use the factory - * {@link java.lang.constant.DynamicConstantDesc#ofCanonical(DirectMethodHandleDesc, java.lang.String, ClassDesc, ConstantDesc[])}, + * {@link java.lang.constant.DynamicConstantDesc#ofCanonical(DirectMethodHandleDesc, java.lang.String, ClassDesc, ConstantDesc[]) DynamicConstantDesc.ofCanonical}, * which will inspect the bootstrap and, for well-known bootstraps, return * a more specific subtype of {@link java.lang.constant.DynamicConstantDesc}, such as * {@link java.lang.Enum.EnumDesc}. diff -r 8bf9268df0e2 -r 4ddd3c410a85 src/java.base/share/classes/java/lang/invoke/TypeDescriptor.java --- a/src/java.base/share/classes/java/lang/invoke/TypeDescriptor.java Thu Dec 13 15:31:05 2018 +0100 +++ b/src/java.base/share/classes/java/lang/invoke/TypeDescriptor.java Thu Dec 13 10:35:09 2018 -0500 @@ -61,7 +61,8 @@ boolean isArray(); /** - * Does this field descriptor describe a primitive type? + * Does this field descriptor describe a primitive type (including void.) + * * @return whether this field descriptor describes a primitive type */ boolean isPrimitive(); diff -r 8bf9268df0e2 -r 4ddd3c410a85 src/java.base/share/classes/java/lang/invoke/VarHandle.java --- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java Thu Dec 13 15:31:05 2018 +0100 +++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java Thu Dec 13 10:35:09 2018 -0500 @@ -1864,6 +1864,16 @@ } } + /** + * Compare this {@linkplain VarHandle} with another object for equality. + * Two {@linkplain VarHandle}s are considered equal if they both describe the + * same instance field, both describe the same static field, both describe + * array elements for arrays with the same component type, or both describe + * the same component of an off-heap structure. + * + * @param o the other object + * @return Whether this {@linkplain VarHandle} is equal to the other object + */ @Override public final boolean equals(Object o) { if (this == o) return true; @@ -1883,6 +1893,12 @@ abstract int internalHashCode(); + /** + * Returns a compact textual description of this {@linkplain VarHandle}, + * including the type of variable described, and a description of its coordinates. + * + * @return A compact textual description of this {@linkplain VarHandle} + */ @Override public final String toString() { return String.format("VarHandle[varType=%s, coord=%s]", @@ -2272,6 +2288,14 @@ } } + /** + * Returns a compact textual description of this constant description. + * For a field {@linkplain VarHandle}, includes the owner, name, and type + * of the field, and whether it is static; for an array {@linkplain VarHandle}, + * the name of the component type. + * + * @return A compact textual description of this descriptor + */ @Override public String toString() { switch (kind) { diff -r 8bf9268df0e2 -r 4ddd3c410a85 test/jdk/java/lang/constant/ClassDescTest.java --- a/test/jdk/java/lang/constant/ClassDescTest.java Thu Dec 13 15:31:05 2018 +0100 +++ b/test/jdk/java/lang/constant/ClassDescTest.java Thu Dec 13 10:35:09 2018 -0500 @@ -244,6 +244,29 @@ testBadNestedClasses(ClassDesc.ofDescriptor(p.descriptor), "any"); testBadNestedClasses(ClassDesc.ofDescriptor(p.descriptor), "any", "other"); } + + ClassDesc stringDesc = ClassDesc.ofDescriptor("Ljava/lang/String;"); + ClassDesc stringArrDesc = stringDesc.arrayType(255); + try { + ClassDesc arrGreaterThan255 = stringArrDesc.arrayType(); + fail("can't create an array type descriptor with more than 255 dimensions"); + } catch (IllegalStateException e) { + // good + } + String descWith255ArrayDims = new String(new char[255]).replace('\0', '['); + try { + ClassDesc arrGreaterThan255 = ClassDesc.ofDescriptor(descWith255ArrayDims + "[Ljava/lang/String;"); + fail("can't create an array type descriptor with more than 255 dimensions"); + } catch (IllegalArgumentException e) { + // good + } + try { + ClassDesc arrWith255Dims = ClassDesc.ofDescriptor(descWith255ArrayDims + "Ljava/lang/String;"); + arrWith255Dims.arrayType(1); + fail("can't create an array type descriptor with more than 255 dimensions"); + } catch (IllegalArgumentException e) { + // good + } } private void testBadNestedClasses(ClassDesc cr, String firstNestedName, String... moreNestedNames) {