How to get Method Parameter names in Java 8 using reflection?

java, java-8, method-parameters, reflection

Solution

How can i get these method parameter names?

Basically, you need to:

- get a reference to a `Class`

- From the `Class`, get a reference to a `Method` by calling `getDeclaredMethod()` or `getDeclaredMethods()` which returns references to `Method` objects

- From the `Method` object, call (new as of Java 8) `getParameters()` which returns an array of `Parameter` objects

- On the `Parameter` object, call `getName()`

Class<String> clz = String.class;
for (Method m : clz.getDeclaredMethods()) {
   System.err.println(m.getName());
   for (Parameter p : m.getParameters()) {
      System.err.println("  " + p.getName());
   }
}

Output:

...
indexOf
  arg0
indexOf
  arg0
  arg1
...

Also as per my knowledge .class files do not store formal parameter. Then how can i get them using reflection?

See the javadoc for `Parameter.getName()`:

... If the parameter's name is present, then this method returns the name provided by the class file. Otherwise, this method synthesizes a name of the form argN, where N is the index of the parameter in the descriptor of the method which declares the parameter.

Whether a JDK supports this, is implementation specific (as you can see form the above output, build 125 of JDK 8 does not support it). The class file format supports optional attributes which can be used by a specific JVM/javac implementation and which are ignored by other implementations which do not support it.

Note that you could even generate the above output with `arg0`, `arg1`, ... with pre Java 8 JVMs - all you need to know is the parameter count which is accessible through `Method.getParameterTypes()`:

Class<String> clz = String.class;
for (Method m : clz.getDeclaredMethods()) {
  System.err.println(m.getName());
  int paramCount = m.getParameterTypes().length;
  for (int i = 0;  i < paramCount;  i++) {
    System.err.println("  arg" + i);
  }
}

What is new with JDK 8 is that there is an extended API and the possibility for JVMs to provide the real parameter names instead of `arg0`, `arg1`, ...

Supporting such optional features is possible through optional attributes which can be attached to the various class file structures. See 4.6. Methods for the `method_info` structure within a class file. See also 4.7.1. Defining and Naming New Attributes in the JVM spec.

Since with JDK 8, the class file version will be incremented to 52, it would also be possible to change the file format itself to support this feature.

See also JEP 118: Access to Parameter Names at Runtime for more information and implementation alternatives. The proposed implementation model is to add an optional attribute which stores the parameter names. Since the class file format already supports these optional attributes, this would even be possible in a way so that the class files can still be used by older JVMs, where they are simply ignored as demanded by the spec:

Java Virtual Machine implementations are required to silently ignore attributes they do not recognize.

Update

As suggested by @assylias, the source needs to be compiled with the `javac` command line option `-parameters` in order to add the meta data for parameter name reflection to the class file. However, this will of course only affect code compiled with this option - the code above will still print `arg0`, `arg1` etc. since the runtime libraries are not be compiled with this flag and hence do not contain the necessary entries in the class files.

Problem

Java 8 has the ability to acquire method parameter names using Reflection API. How can I get these method parameter names? As per my knowledge, class files do not store formal parameter names. How can I get these using reflection?

Original source

Related problems