4848 */
4949public class ClassUtils {
5050
51+ /**
52+ * The JVM {@code CONSTANT_Class_info} structure defines an array type descriptor is valid only if it represents 255 or fewer dimensions.
53+ *
54+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.4.1">JVM: Array dimension limits in JVM Specification CONSTANT_Class_info</a>
55+ */
56+ private static final int MAX_JVM_ARRAY_DIMENSION = 255 ;
57+
5158 /**
5259 * Inclusivity literals for {@link #hierarchy(Class, Interfaces)}.
5360 *
@@ -520,11 +527,16 @@ private static String getCanonicalName(final String name) {
520527 * supports the syntaxes "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}",
521528 * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}".
522529 *
523- * @param classLoader the class loader to use to load the class
524- * @param className the class name
525- * @return the class represented by {@code className} using the {@code classLoader}
526- * @throws NullPointerException if the className is null
527- * @throws ClassNotFoundException if the class is not found
530+ * @param classLoader the class loader to use to load the class.
531+ * @param className the class name.
532+ * @return the class represented by {@code className} using the {@code classLoader}.
533+ * @throws NullPointerException if the className is null.
534+ * @throws ClassNotFoundException if the class is not found.
535+ * @throws IllegalArgumentException Thrown if the class name represents an array with more dimensions than the JVM supports, 255.
536+ * @see Class#forName(String, boolean, ClassLoader)
537+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.4.1">JVM: Array dimension limits in JVM Specification CONSTANT_Class_info</a>
538+ * @see <a href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-6.html#jls-6.7">JLS: Fully Qualified Names and Canonical Names</a>
539+ * @see <a href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-13.html#jls-13.1">JLS: The Form of a Binary</a>
528540 */
529541 public static Class <?> getClass (final ClassLoader classLoader , final String className ) throws ClassNotFoundException {
530542 return getClass (classLoader , className , true );
@@ -535,12 +547,17 @@ public static Class<?> getClass(final ClassLoader classLoader, final String clas
535547 * syntaxes "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}", "{@code [Ljava.util.Map.Entry;}", and
536548 * "{@code [Ljava.util.Map$Entry;}".
537549 *
538- * @param classLoader the class loader to use to load the class
539- * @param className the class name
540- * @param initialize whether the class must be initialized
541- * @return the class represented by {@code className} using the {@code classLoader}
542- * @throws NullPointerException if the className is null
543- * @throws ClassNotFoundException if the class is not found
550+ * @param classLoader the class loader to use to load the class.
551+ * @param className the class name.
552+ * @param initialize whether the class must be initialized.
553+ * @return the class represented by {@code className} using the {@code classLoader}.
554+ * @throws NullPointerException if the className is null.
555+ * @throws ClassNotFoundException if the class is not found.
556+ * @throws IllegalArgumentException Thrown if the class name represents an array with more dimensions than the JVM supports, 255.
557+ * @see Class#forName(String, boolean, ClassLoader)
558+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.4.1">JVM: Array dimension limits in JVM Specification CONSTANT_Class_info</a>
559+ * @see <a href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-6.html#jls-6.7">JLS: Fully Qualified Names and Canonical Names</a>
560+ * @see <a href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-13.html#jls-13.1">JLS: The Form of a Binary</a>
544561 */
545562 public static Class <?> getClass (final ClassLoader classLoader , final String className , final boolean initialize ) throws ClassNotFoundException {
546563 // This method was re-written to avoid recursion and stack overflows found by fuzz testing.
@@ -569,6 +586,11 @@ public static Class<?> getClass(final ClassLoader classLoader, final String clas
569586 * @return the class represented by {@code className} using the current thread's context class loader
570587 * @throws NullPointerException if the className is null
571588 * @throws ClassNotFoundException if the class is not found
589+ * @throws IllegalArgumentException Thrown if the class name represents an array with more dimensions than the JVM supports, 255.
590+ * @see Class#forName(String, boolean, ClassLoader)
591+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.4.1">JVM: Array dimension limits in JVM Specification CONSTANT_Class_info</a>
592+ * @see <a href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-6.html#jls-6.7">JLS: Fully Qualified Names and Canonical Names</a>
593+ * @see <a href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-13.html#jls-13.1">JLS: The Form of a Binary</a>
572594 */
573595 public static Class <?> getClass (final String className ) throws ClassNotFoundException {
574596 return getClass (className , true );
@@ -579,11 +601,16 @@ public static Class<?> getClass(final String className) throws ClassNotFoundExce
579601 * implementation supports the syntaxes "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}",
580602 * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}".
581603 *
582- * @param className the class name
583- * @param initialize whether the class must be initialized
584- * @return the class represented by {@code className} using the current thread's context class loader
585- * @throws NullPointerException if the className is null
586- * @throws ClassNotFoundException if the class is not found
604+ * @param className the class name.
605+ * @param initialize whether the class must be initialized.
606+ * @return the class represented by {@code className} using the current thread's context class loader.
607+ * @throws NullPointerException if the className is null.
608+ * @throws ClassNotFoundException if the class is not found.
609+ * @throws IllegalArgumentException Thrown if the class name represents an array with more dimensions than the JVM supports, 255.
610+ * @see Class#forName(String, boolean, ClassLoader)
611+ * @see <a href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.4.1">JVM: Array dimension limits in JVM Specification CONSTANT_Class_info</a>
612+ * @see <a href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-6.html#jls-6.7">JLS: Fully Qualified Names and Canonical Names</a>
613+ * @see <a href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-13.html#jls-13.1">JLS: The Form of a Binary</a>
587614 */
588615 public static Class <?> getClass (final String className , final boolean initialize ) throws ClassNotFoundException {
589616 final ClassLoader contextCL = Thread .currentThread ().getContextClassLoader ();
@@ -1494,17 +1521,22 @@ public static Class<?> primitiveToWrapper(final Class<?> cls) {
14941521 /**
14951522 * Converts a class name to a JLS style class name.
14961523 *
1497- * @param className the class name
1498- * @return the converted name
1499- * @throws NullPointerException if the className is null
1524+ * @param className the class name.
1525+ * @return the converted name.
1526+ * @throws NullPointerException if the className is null.
1527+ * @throws IllegalArgumentException Thrown if the class name represents an array with more dimensions than the JVM supports, 255.
15001528 */
15011529 private static String toCanonicalName (final String className ) {
15021530 String canonicalName = StringUtils .deleteWhitespace (className );
15031531 Objects .requireNonNull (canonicalName , "className" );
15041532 final String arrayMarker = "[]" ;
1533+ int arrayDim = 0 ;
15051534 if (canonicalName .endsWith (arrayMarker )) {
15061535 final StringBuilder classNameBuffer = new StringBuilder ();
15071536 while (canonicalName .endsWith (arrayMarker )) {
1537+ if (++arrayDim > MAX_JVM_ARRAY_DIMENSION ) {
1538+ throw new IllegalArgumentException ("Array dimension greater than JVM specification maximum of 255." );
1539+ }
15081540 canonicalName = canonicalName .substring (0 , canonicalName .length () - 2 );
15091541 classNameBuffer .append ("[" );
15101542 }
0 commit comments