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

javac does not accept classfiles with certain permitted RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 24
    • tools
    • None
    • behavioral
    • low
    • There is no intent to change javac to produce errors for classfiles that do not produce errors now. It is not the intent to change any the content of classfiles written by javac.
    • File or wire format, Other
    • Implementation

      Summary

      javac does not accept some classfiles which contain valid RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes, as specified in JVMS 4.7.18 and 4.7.19.

      Problem

      The RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes, as specified in JVMS 4.7.18 and 4.7.19 do not currently put any requirements on the number of entries in the attributes, or even the ordering of the entries. javac, however, only accepts classfiles where the number of entries in the attributes match its internal parameter count for the given method. javac rejects all other classfiles.

      Historical considerations:

      In JDK 8 and below, the attributes were specified as:

      The i'th entry in the table corresponds to the i'th formal parameter in the method descriptor (§4.3.3).

      https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.18

      javac was not implementing the specification correctly in two aspects:

      • when writing a classfile, when the Signature attribute was used for a method, it was only producing as many entries of these attributes as there were parameters in the Signature attribute
      • when reading a classfile, if the Signature attribute was present for the method, javac expected the attribute to have exactly as many entries as there were parameters in the Signature attribute

      In JDK 9, the wording for these attributes has been changed to:

      The i'th entry in the parameter_annotations table may, but is not required to, correspond to the i'th parameter descriptor in the method descriptor (§4.3.3).

      https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.18

      This change made the classfile written by javac legal, but also made many other forms of the classfiles legal. javac was never adjusted to this change.

      Solution

      Regardless of the number of entries in the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes, javac will never produce an error.

      As the wording in the specification does not allow to reliably map the annotations to the parameters, it is proposed javac will use a number of heuristics to do the mapping. If none of these heuristics will yield a result, javac will ignore the attributes.

      Note the heuristics below are intended to not change result for any classfiles which javac can read without errors currently. They only add new cases which are accepted by javac.

      The proposal herein only concerns javac. Other parts of the JDK (notably the core reflection) may need to be adjusted separately, and are outside of the scope of this change.

      Specification

      The proposed heuristics are (if at least one of RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes is present):

      • if both RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes are present, javac will ignore them both with a warning unless they have the same number of entries
      • if, for the given method, there is the Signature attribute, and the number of entries in the attributes is the same as the number of parameters in the Signature attribute, the entries in the attributes will be used in order to fill the parameters from the Signature attribute,
      • otherwise, if for the given method, there is no Signature attribute, if the method is a constructor, and the class is heuristically determined to be an inner class (the class is a non-static inner class and is determined to be neither an anonymous class, nor a local class), the first parameter is stripped, and if the number of parameters of this adjusted type is the same as the number of entries in the attributes, the entries in the attributes will be used in order to fill the parameters from this adjusted type,
      • otherwise, if for the given method, there is no Signature attribute and if the method is not a constructor of a heuristically determined innerclass, and the number of entries in the attributes is the same as the number of parameters in the method's descriptor, the entries in the attributes will be used in order to fill the parameters from method's descritor,
      • otherwise, if there is MethodParameters attribute for the method, and the number of non-synthetic and non-mandatory parameters as per the MethodParameters attribute is the same as the number of entries in the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes, the entries in the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes will be used in order to fill the annotations on the non-synthetic and non-mandated parameters,
      • otherwise, if there is MethodParameters attribute for the method, and the number parameters in the method's descritor is the same as the number of entries in the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes, the entries in the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes that correspond to either synthetic and mandated parameters will be ignored, and the others will be used in order to fill the annotations on the non-synthetic and non-mandated parameters,
      • otherwise, if there is no MethodParameters, the current method is a constructor for an enum types, there is no Signature attribute and the number of parameters in the method's descriptor minus 2 is the same as the number of entries in the the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes, the entries in the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes will be used in order to fill the annotations for the parameters starting from the 2nd parameter,
      • otherwise, if the given classfile represents an (direct or indirect) local class, and there is no Signature attribute, and the number of parameters in the method's descriptor is greater than the number of entries in the the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes, the entries in the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes will be used in order to fill the annotations for the parameters starting from the 1st parameter.

      javac will never produce an error based on the number of entries in the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes. javac will produce warnings if:

      • the number of entries in the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes differ
      • none of the above heuristics applies

            jlahoda Jan Lahoda
            jlahoda Jan Lahoda
            Chen Liang
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: