One of the lesser advertised new features of JDK 8 is the optional ability to include parameter metadata in compiled Java classes [JDK Enhancement Proposal (JEP) 118]. This feature allows Java applications to access this parameter metadata information at runtime via reflection.
The Java Tutorials' Reflection API trail includes a lesson called Obtaining Names of Method Parameters that discusses and demonstrates how to apply this new feature in Java 8. The lesson includes an example Java class MethodParameterSpy that can be run against a provided Java class to indicate characteristics of method and constructor parameters. This lesson also emphasizes that this is an optional feature because storing additional parameter metadata in .class files increases the size of those files. The lesson also points out that there may be some cases where parameter names have sensitive information that the developer does not want available in the compiled .class files.
The additional parameter metadata can be included in .class files compiled in Java 8 by passing the -parameters option to the javac compiler. This -parameters option is also shown when one types javac -help as shown in the next screen snapshot.
The Oracle TechNotes page on javac indicates how this additional method/constructor parameter data can be accessed at runtime: "Stores formal parameter names of constructors and methods in the generated class file so that the method java.lang.reflect.Executable.getParameters from the Reflection API can retrieve them." The following code snippet (class called ParameterDisplayer) demonstrates this (emphasis is on the displayParametersMetadata(String[]) method).
ParameterDisplayer.java
I had initially thought about running this class against a well-known class of the JDK, but realized that would not be too helpful because those classes are not likely to have been built with the -parameters option. Therefore, I have created a simple example class to aid with the demonstration. It is called ManyMethods and is shown next.
ManyMethods.java
The next two screen snapshots demonstrate running ParameterDisplayer against instances of ManyMethods compiled without and with the -parameters option. The most notable differences are that the parameter names are not provided when compiled without the -parameters option. Also, there is no trusted information on whether the parameter is final when compiled without the -parameters option. The Parameter.getModifiers() method does not include final when compiled without -parameters whether or not the parameter is actually final.
The ParameterDisplayer class uses Parameter.isNamePresent() to programmatically identify that the parameter name is not present (when not compiled with the -parameters option). Had that check not been made, the parameter name returned by Parameter.getName() would have been "arg" plus the number of the parameter (arg0 for the first parameter, arg1 for the second parameter, and so on).
Two of the three methods in ManyMethods class that had a parameter had the final modifier on that parameter. These cases were correctly identified by reflection using Parameter.getModifiers() only when the class was compiled with the -parameters option.
Slightly Related Side Note: Sun/Oracle tools documentation has always consisted of a "windows" page and a "solaris" page, with the latter typically being used to describe how the particular tool works on all flavors on Linux and Unix. I noted that this has changed with the Java 8 documentation. This documentation still has a "windows" version, but the Unix/Linux version now has "unix" in its URL. To illustrate this, here are the URLs for Java SE 7 and Java SE 8 javac tool pages:
http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javac.html
http://docs.oracle.com/javase/8/docs/technotes/tools/unix/javac.html
http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html
http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javac.html
Returning to the new (with Java 8) Parameter class, it's worth noting that there is an increase in compiled .class files that store this additional parameter metadata. For my ManyMethods class shown above, the .class file was enlarged from 909 bytes to 961 bytes.
Constructor, like Method, extends Executable, and so the Constructor class enjoys the same getParameters method as Method. Java 8 provides more detail on method and constructor parameters when the code is explicitly compiled with that extra information.
Original posting available at http://marxsoftware.blogspot.com/ (Inspired by Actual Events)