Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8296196

Class.getEnumConstants() throws undocumented ClassCastException and NullPointerException

XMLWordPrintable

    • b24
    • generic
    • generic
    • Verified

      A DESCRIPTION OF THE PROBLEM :
      When `Class.getEnumConstants()` is called on a bad enum class where `values()` is an instance method, or returns a non‑array, then it throws `NullPointerException` or `ClassCastException` respectively.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached Java and Jasm program. Might need https://github.com/openjdk/asmtools/pull/46 to compile successfully.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The program completes successfully.
      ACTUAL -
      The program throws `java.lang.AssertionError`:
      ```
      Exception in thread "main" java.lang.AssertionError: [java.lang.NullPointerException, java.lang.ClassCastException: class java.lang.Object cannot be cast to class [Ljava.lang.Object; (java.lang.Object and [Ljava.lang.Object; are in module java.base of loader 'bootstrap')]
      at Test.main(Test.java:28)
      Suppressed: java.lang.NullPointerException
      at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:76)
      at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:52)
      at java.base/java.lang.reflect.Method.invoke(Method.java:578)
      at java.base/java.lang.Class.getEnumConstantsShared(Class.java:3894)
      at java.base/java.lang.Class.getEnumConstants(Class.java:3869)
      at Test.main(Test.java:14)
      Suppressed: java.lang.ClassCastException: class java.lang.Object cannot be cast to class [Ljava.lang.Object; (java.lang.Object and [Ljava.lang.Object; are in module java.base of loader 'bootstrap')
      at java.base/java.lang.Class.getEnumConstantsShared(Class.java:3894)
      at java.base/java.lang.Class.getEnumConstants(Class.java:3869)
      at Test.main(Test.java:21)
      ```

      ---------- BEGIN SOURCE ----------
      /// BEGIN JAVA
      import java.util.ArrayList;
      import java.util.List;

      final class Test {
      public static void main(final String... args) throws Throwable {
      final List<Throwable> errors = new ArrayList<>();

      try {
      final Object actual = BadEnum1.class.getEnumConstants();
      if (actual != null) throw new AssertionError("Expected BadEnum1.class.getEnumConstants() to return null, got " + actual);
      } catch (final Throwable t) {
      errors.add(t);
      }

      try {
      final Object actual = BadEnum2.class.getEnumConstants();
      if (actual != null) throw new AssertionError("Expected BadEnum2.class.getEnumConstants() to return null, got " + actual);
      } catch (final Throwable t) {
      errors.add(t);
      }

      if (!errors.isEmpty()) {
      final AssertionError err = new AssertionError(List.copyOf(errors));
      errors.forEach(err::addSuppressed);
      throw err;
      }
      }
      }
      /// END JAVA

      /// BEGIN JASM
      super final enum class BadEnum1
      extends java/lang/Enum
      version 52:0
      {
      Signature "Ljava/lang/Enum<LBadEnum1;>;";

      private static final synthetic Field $VALUES:"[LBadEnum1;";

      public Method values:"()[LBadEnum1;"
      stack 1
      {
      getstatic Field $VALUES:"[LBadEnum1;";
      invokevirtual Method "[LBadEnum1;".clone:"()Ljava/lang/Object;";
      checkcast class "[LBadEnum1;";
      areturn;
      }

      public static Method valueOf:"(Ljava/lang/String;)LBadEnum1;"
      stack 2
      0: #{name mandated}
      {
      ldc class BadEnum1;
      aload_0;
      invokestatic Method java/lang/Enum.valueOf:"(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;";
      checkcast class BadEnum1;
      areturn;
      }

      private Method "<init>":"(Ljava/lang/String;I)V":"()V"
      stack 3
      0: #{$enum$name synthetic}
      1: #{$enum$ordinal synthetic}
      {
      aload_0;
      aload_1;
      iload_2;
      invokespecial Method java/lang/Enum."<init>":"(Ljava/lang/String;I)V";
      return;
      }

      private static synthetic Method $values:"()[LBadEnum1;"
      stack 1
      {
      iconst_0;
      anewarray class BadEnum1;
      areturn;
      }

      static Method "<clinit>":"()V"
      stack 1
      {
      invokestatic Method $values:"()[LBadEnum1;";
      putstatic Field $VALUES:"[LBadEnum1;";
      return;
      }
      }

      super final enum class BadEnum2
      extends java/lang/Enum
      version 52:0
      {
      Signature "Ljava/lang/Enum<LBadEnum2;>;";

      private static final synthetic Field $VALUES:"[LBadEnum2;";

      public static Method values:"()Ljava/lang/Object;"
      stack 2
      {
      new class java/lang/Object;
      dup;
      invokespecial Method java/lang/Object."<init>":"()V";
      areturn;
      }

      public static Method valueOf:"(Ljava/lang/String;)LBadEnum2;"
      stack 2
      0: #{name mandated}
      {
      ldc class BadEnum2;
      aload_0;
      invokestatic Method java/lang/Enum.valueOf:"(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;";
      checkcast class BadEnum2;
      areturn;
      }

      private Method "<init>":"(Ljava/lang/String;I)V":"()V"
      stack 3
      0: #{$enum$name synthetic}
      1: #{$enum$ordinal synthetic}
      {
      aload_0;
      aload_1;
      iload_2;
      invokespecial Method java/lang/Enum."<init>":"(Ljava/lang/String;I)V";
      return;
      }

      private static synthetic Method $values:"()[LBadEnum2;"
      stack 1
      {
      iconst_0;
      anewarray class BadEnum2;
      areturn;
      }

      static Method "<clinit>":"()V"
      stack 1
      {
      invokestatic Method $values:"()[LBadEnum2;";
      putstatic Field $VALUES:"[LBadEnum2;";
      return;
      }
      }
      /// END JASM
      ---------- END SOURCE ----------

      FREQUENCY : always


        1. BadEnum.jasm
          2 kB
        2. Test.java
          0.8 kB

            asotona Adam Sotona
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

              Created:
              Updated:
              Resolved: