JEP 118: Access to Parameter Names at Runtime
|Author||Joseph D. Darcy|
|Component||specification / vm|
|JSRs||269 MR, 337|
|Discussion||enhanced dash metadata dash spec dash discuss at openjdk dot java dot net|
|Endorsed by||Brian Goetz|
Provide a mechanism to easily and reliably retrieve the parameter names of methods and constructors at runtime via core reflection.
The primary goal is to improve the readability of code which currently uses logically redundant annotations to record parameter names. A secondary goal is to improve IDE capabilities by making parameter names more widely available.
Java uses positional parameter passing, that is, the first argument in
a method call is passed in as the first parameter, the second argument
in a method call is passed in as the second parameter, and so on.
Many other systems use nominal parameter passing where something like
a set of name:value pairs is passed along instead. When Java code
interfaces with a nominal parameter passing system, the names of the
parameters from the original Java source are often needed to construct
a proper name:value mapping. Unfortunately, there is no reliable way
within the existing Java SE APIs to retrieve the parameter names of a
method or constructor. As a workaround, various APIs have defined
their own "
@ParameterName" annotations, which leads to very
cluttered looking source code.
Java IDEs can now auto-generate template code for creating a concrete subtype of an interface or abstract class. If the source code is available, the parameter names from the source can be used in the generated code. If the parameter name information were reliably stored in class files, useful names could be generated in more cases.
Depending on the approach taken, the long-standing inability to determine when the number of parameters in the source code of a method differs from the number or parameters in the compiled form of the method may also be remedied.
The proposed approach is to create an optional new JVM attribute in version 52.0 class files to store information about the parameters of a JVM-level method. That information includes:
- the source-level name of a parameter, if any
- modifiers of the parameter, if any
A parameter of a method or constructor in a class file might not have any corresponding parameter in the source code. For example,
As an implementation choice,
javacprepends two synthetic parameters to
enumconstructors to allow the compiler to pass in name and ordinal information. Other compilers, including
javacimplementations in different releases, are free to use another implementation technique to pass along this information.
The constructors for anonymous inner classes generally have another parameter prepended to the constructor's argument list to allow the outer this information to be passed along. However, anonymous inner class constructors in a static context, such as a
staticinitializer block, need not have such a parameter.
Given the availability of this information, core reflection could then
java.lang.reflect.Parameter class to allow retrieval of this
information. A method to return an array of
Parameter objects would
be defined in
java.lang.reflect.Executable, which is a common
Constructor. More direct modeling of
parameter information is preferable to continued indirect modeling as
Method.getParameterAnnotations where the behavior of synthetic
parameters is not well defined.
To avoid introducing unnecessary compatibility restrictions, a distinction should be made between parameter names available for informative purposes only and parameters names which are being provided as an public interface of the method or constructor. An annotation is a good candidate to concisely indicate whether or not particular parameter names are serving as an exported interface.
The design is not finalized, but alternatives include storing the name information in parameter annotations synthesized by the compiler. The trigger to indicate those parameter annotation should be synthesized could be the presences of an annotation on the class or interface or even a *meta*annotation on the annotation type of a annotation found on a class or interface.
Assuming the general approach in the description section, much of the implementation would fall into the area of the mostly implicit compiler specification, that is, the specification of how a Java compiler translates Java source code into class files (or other executable output format). With the source code to class file mapping being under test, there is a natural match to the coverage areas of JCK tests, but to be covered under the JCK, some governing Java SE specification is needed.
For a given design, it is relatively straightforward to use annotation processors to generate different code samples spanning the space of variables to be tested.
Risks and Assumptions
By introducing a new JVM attribute, the coordination costs of this
change rise considerably since tools which consume class files, from
pack200 to the JVM itself, need to be updated to handle the new
Multiple IDE support during the development of JDK 8 would help validate the operation of this feature.
In JDK components, fully implementing this feature requires coordinated compiler, libraries, and JVM changes.
- Compatibility: By default, the names of parameters should not be added to the compatibility burden of a method or constructor.
- Performance/scalability: The performance of
javacshould be tracked to verify a performance regression is not introduced.