src/java.base/share/classes/java/lang/constant/ClassDesc.java
changeset 53019 4ddd3c410a85
parent 52914 4fa75d8ad418
child 53224 bae765528fcc
equal deleted inserted replaced
53018:8bf9268df0e2 53019:4ddd3c410a85
   110      *
   110      *
   111      * @apiNote
   111      * @apiNote
   112      *
   112      *
   113      * A field type descriptor string for a non-array type is either
   113      * A field type descriptor string for a non-array type is either
   114      * a one-letter code corresponding to a primitive type
   114      * a one-letter code corresponding to a primitive type
   115      * ({@code J,I,C,S,B,D,F,Z,V}), or the letter {@code L}, followed
   115      * ({@code "J", "I", "C", "S", "B", "D", "F", "Z", "V"}), or the letter {@code "L"}, followed
   116      * by the fully qualified binary name of a class, followed by {@code ;}.
   116      * by the fully qualified binary name of a class, followed by {@code ";"}.
   117      * A field type descriptor for an array type is the character {@code [}
   117      * A field type descriptor for an array type is the character {@code "["}
   118      * followed by the field descriptor for the component type.  Examples of
   118      * followed by the field descriptor for the component type.  Examples of
   119      * valid type descriptor strings include {@code Ljava/lang/String;}, {@code I},
   119      * valid type descriptor strings include {@code "Ljava/lang/String;"}, {@code "I"},
   120      * {@code [I}, {@code V}, {@code [Ljava/lang/String;}, etc.
   120      * {@code "[I"}, {@code "V"}, {@code "[Ljava/lang/String;"}, etc.
   121      * for more detail.
   121      * See JVMS 4.3.2 ("Field Descriptors") for more detail.
   122      *
   122      *
   123      * @param descriptor a field descriptor string
   123      * @param descriptor a field descriptor string
   124      * @return a {@linkplain ClassDesc} describing the desired class
   124      * @return a {@linkplain ClassDesc} describing the desired class
   125      * @throws NullPointerException if any argument is {@code null}
   125      * @throws NullPointerException if any argument is {@code null}
   126      * @throws IllegalArgumentException if the name string is not in the
   126      * @throws IllegalArgumentException if the name string is not in the
   127      * correct format
   127      * correct format
   128      * @jvms 4.3.2 Field Descriptors
   128      * @jvms 4.3.2 Field Descriptors
       
   129      * @jvms 4.4.1 The CONSTANT_Class_info Structure
   129      */
   130      */
   130     static ClassDesc ofDescriptor(String descriptor) {
   131     static ClassDesc ofDescriptor(String descriptor) {
   131         requireNonNull(descriptor);
   132         requireNonNull(descriptor);
       
   133         int depth = ConstantUtils.arrayDepth(descriptor);
       
   134         if (depth > ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
       
   135             throw new IllegalArgumentException(String.format("Cannot create an array type descriptor with more than %d dimensions",
       
   136                     ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS));
       
   137         }
   132         return (descriptor.length() == 1)
   138         return (descriptor.length() == 1)
   133                ? new PrimitiveClassDescImpl(descriptor)
   139                ? new PrimitiveClassDescImpl(descriptor)
   134                : new ReferenceClassDescImpl(descriptor);
   140                : new ReferenceClassDescImpl(descriptor);
   135     }
   141     }
   136 
   142 
   137     /**
   143     /**
   138      * Returns a {@linkplain ClassDesc} for an array type whose component type
   144      * Returns a {@linkplain ClassDesc} for an array type whose component type
   139      * is described by this {@linkplain ClassDesc}.
   145      * is described by this {@linkplain ClassDesc}.
   140      *
   146      *
   141      * @return a {@linkplain ClassDesc} describing the array type
   147      * @return a {@linkplain ClassDesc} describing the array type
       
   148      * @throws IllegalStateException if the resulting {@linkplain ClassDesc} would have an array rank of greater than 255
       
   149      * @jvms 4.4.1 The CONSTANT_Class_info Structure
   142      */
   150      */
   143     default ClassDesc arrayType() {
   151     default ClassDesc arrayType() {
       
   152         int depth = ConstantUtils.arrayDepth(descriptorString());
       
   153         if (depth >= ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
       
   154             throw new IllegalStateException(String.format("Cannot create an array type descriptor with more than %d dimensions",
       
   155                     ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS));
       
   156         }
   144         return arrayType(1);
   157         return arrayType(1);
   145     }
   158     }
   146 
   159 
   147     /**
   160     /**
   148      * Returns a {@linkplain ClassDesc} for an array type of the specified rank,
   161      * Returns a {@linkplain ClassDesc} for an array type of the specified rank,
   149      * whose component type is described by this {@linkplain ClassDesc}.
   162      * whose component type is described by this {@linkplain ClassDesc}.
   150      *
   163      *
   151      * @param rank the rank of the array
   164      * @param rank the rank of the array
   152      * @return a {@linkplain ClassDesc} describing the array type
   165      * @return a {@linkplain ClassDesc} describing the array type
   153      * @throws IllegalArgumentException if the rank is zero or negative
   166      * @throws IllegalArgumentException if the rank is less than zero or if the rank of the resulting array type is
       
   167      * greater than 255
       
   168      * @jvms 4.4.1 The CONSTANT_Class_info Structure
   154      */
   169      */
   155     default ClassDesc arrayType(int rank) {
   170     default ClassDesc arrayType(int rank) {
   156         if (rank <= 0)
   171         int currentDepth = ConstantUtils.arrayDepth(descriptorString());
   157             throw new IllegalArgumentException("rank: " + rank);
   172         if (rank <= 0 || currentDepth + rank > ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS)
       
   173             throw new IllegalArgumentException("rank: " + currentDepth + rank);
   158         return ClassDesc.ofDescriptor("[".repeat(rank) + descriptorString());
   174         return ClassDesc.ofDescriptor("[".repeat(rank) + descriptorString());
   159     }
   175     }
   160 
   176 
   161     /**
   177     /**
   162      * Returns a {@linkplain ClassDesc} for a nested class of the class or
   178      * Returns a {@linkplain ClassDesc} for a nested class of the class or
   163      * interface type described by this {@linkplain ClassDesc}.
   179      * interface type described by this {@linkplain ClassDesc}.
       
   180      *
       
   181      * @apiNote
       
   182      *
       
   183      * Example: If descriptor {@code d} describes the class {@code java.util.Map}, a
       
   184      * descriptor for the class {@code java.util.Map.Entry} could be obtained
       
   185      * by {@code d.nested("Entry")}.
   164      *
   186      *
   165      * @param nestedName the unqualified name of the nested class
   187      * @param nestedName the unqualified name of the nested class
   166      * @return a {@linkplain ClassDesc} describing the nested class
   188      * @return a {@linkplain ClassDesc} describing the nested class
   167      * @throws NullPointerException if any argument is {@code null}
   189      * @throws NullPointerException if any argument is {@code null}
   168      * @throws IllegalStateException if this {@linkplain ClassDesc} does not
   190      * @throws IllegalStateException if this {@linkplain ClassDesc} does not