JDK 9 RFR of JDK-8074977: Constructor.getAnnotatedParameterTypes returns wrong value
joe.darcy at oracle.com
Sat May 20 21:38:29 UTC 2017
On 5/20/2017 11:00 AM, Peter Levart wrote:
> Hi Joe,
> So enum classes, anonymous classes and local classes don't have a
> standard way of passing synthetic/implicit constructor parameters?
Right; there is no standardized or mandated way for compilers to do
that. Such details are intentionally outside of what the JLS specifies.
Since non-static member classes can be referred to and instances
instantiated from outside of the enclosing class, there has to be a
standardized linkage model in that case for separate compilation, etc.
and that is covered in the JLS. This isn't the case for local and
anonymous classes since there isn't a way to refer to such classes from
outside of their immediate declaration context. The instances of such
types can be returned of course and then it is possible for people to
getClass().getConstructors()... their way into the issue.
> Do various compilers do it differently than javac?
IIRC, ecj does compile enum classes differently than javac.
> It's unfortunate but if # of parameter annotations arrays is less than
> the # of parameters, Parameter.getAnnotations() may return wrong
> annotations or throw IndexOutOfBoundException for enums, anonymous and
> local classes. Can't we do anything for them? At least for code
> compiled by javac?
> For example, javac compiles enum classes so that they always prefix
> constructor source parameters with a pair of (String name, int
> ordinal, ...) and so do anonymous enum subclasses provided by enum
> constants (i.e. clazz.isAnonymousClass() &&
> Non-static local classes are compiled so that constructor source
> parameters are prefixed with a single parameter (OuterClass
> outerInstance, ...), while any captured variables follow source parameters
A wrinkle with local classes is that if they occur in a static context,
such as a static initializer block, there is no leading outer instance
This is admittedly not a 100% solution to parameter mismatches and
annotations; however, it is an improvement over the current state of
Ideally, the code for something like Parameters.getAnnotations could do
something like look at the synthetic bit and pair up natural parameters
with annotations if there was a mismatch in the number of parameters and
annotations. Unfortunately, the Parameters.isSynthetic API wasn't
introduced until JDK 8 and that information doesn't have to be available.
> Static local classes are compiled so that constructor source
> parameters come 1st, followed by any captured variables.
> Regards, Peter
> On 05/19/2017 11:31 PM, joe darcy wrote:
>> Please review the webrev to fix
>> JDK-8074977: Constructor.getAnnotatedParameterTypes returns wrong
>> To condense a complicated situation, there are cases where the number
>> of parameters present for a constructor in source code and the number
>> of parameters present for that constructor in the class file differ.
>> One of those cases occurs for the constructor of a non-static member
>> class  where there is a leading parameter to accept the outer this
>> Bug JDK-8074977 reports on a situation where the type annotations on
>> constructor parameters are incorrectly reported. Essentially, an
>> off-by-one error is the cause since the annotation information is
>> stored with respect to the number of parameters present in the source
>> and an additional parameter is present at runtime.
>> An analogous situation exists for declaration annotations and
>> constructor parameters, declaration annotations being the traditional
>> flavor of annotations.
>> Type annotations and declaration annotations are read using different
>> APIs so require separate fixes to detect the additional parameter and
>> make the necessary adjustments in the returned information.
>> The regression tests cover both the type annotation reading API and
>> the two ways of reading declaration annotations on parameters,
>> calling getParameterAnnotations on the constructor or call
>> getParameters on the constructor and then calling getAnnotations on
>> each parameter. The getParameters API was added in JDK 8.
>> Static member and non-static member classes are used as test cases,
>> as are constructors with and without generic type information.
More information about the core-libs-dev