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

Constructor.getAnnotatedParameterTypes returns wrong value for Enums

    XMLWordPrintable

Details

    Description

      A DESCRIPTION OF THE PROBLEM :
      The return result of Constructor.getAnnotatedParameterTypes() for enum constructors are wrong, that it maps annotations on formal parameters to descriptor-based parameters without an offset of 2. The annotation attribute in the class file seems correct, and this issue happens either when -parameter flag of javac is set or not.
      The non-type-annotation equivalent for enum was fixed in JDK-8263763, and the type annotation inner class equivalent was fixed in JDK-8074977.

      May be feasible to unify the offset detection mechanism for both type annotations in TypeAnnotationParser and regular annotations in Executable.handleParameterNumberMismatch, or even that for signatures for formal parameters. Currently there are 3 different systems for mapping them, which is costly for maintenance and is a blind spot in Java Language and JVM specifications.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Write an enum constructor that use TYPE annotations on its parameters. Observe that the type annotations

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The annotated type of the cmp argument should be @TypeAnno Comparator when inspected by reflection; when javac compiles this class with -parameters flag, it should be presented as @Comparator<@TypeAnno String>. The annotated type of the synthetic $enum$name argument (param 0) should be String.
      ACTUAL -
      The annotated type of cmp is Comparator or Comparator<String> (with javac -parameters flag); the annotated type of $enum$name is @TypeAnno String.

      ---------- BEGIN SOURCE ----------
      import java.lang.annotation.*;
      import java.lang.reflect.*;
      import java.util.*;

      enum EnumCtor {
      ;
      EnumCtor(@TypeAnno Comparator<@TypeAnno String> cmp) {} // relevant content

      public static void main(String... args) throws Throwable {
              inspect(EnumCtor.class.getDeclaredConstructor(String.class, Integer.TYPE, Comparator.class));
          }

          static void inspect(Executable ctor) {
              var params = ctor.getParameters();
              System.out.println("Params:\n" + Arrays.toString(params));
              System.out.println("Param types:\n" + Arrays.toString(ctor.getParameterTypes()));
              System.out.println("Generic Params:\n" + Arrays.toString(ctor.getGenericParameterTypes()));
              System.out.println("Annotated Params:\n" + Arrays.toString(ctor.getAnnotatedParameterTypes()));
              System.out.println("Receiver:\n" + ctor.getAnnotatedReceiverType());
              for (int i = 0; i < params.length; i++) {
               var p = params[i];
                  System.out.println("Param " + i + ":\n" + p.getType() + ", " + p.getParameterizedType() + ", " + p.getAnnotatedType());
              }
              System.out.println();
          }

      }

      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.TYPE_USE)
      @interface TypeAnno {}

      ---------- END SOURCE ----------

      FREQUENCY : always


      Attachments

        Issue Links

          Activity

            People

              liach Chen Liang
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: