Paranamer
Paranamer - access to parameter names in Java5, 6, 7, 8
Install / Use
/learn @paul-hammant/ParanamerREADME
Method Parameter Name Access for Java*
- versions PRIOR TO Java <del>7.0</del> 8.0
- Minimum JDK version 8
- Has JDK9's supported parameter name access built in (for JDK9 and above deployments)
What is it?
It is a library that allows the parameter names of non-private methods and constructors to be accessed at runtime. Normally this information is dropped by the compiler. In effect, methods like doSometing(mypkg.Person toMe)
currently look like doSomething(mypackage.Person ???) to people using Java's reflection to inspect methods. Well, normal prior to JDK 9.
Historically parameter name access has not been very useful to Java application developers, but with the advent of advanced scripting languages and web action frameworks for the JVM it is of increasing importance to be able to leverage a method's parameter names. Scripting languages like Groovy and JRuby, web action frameworks like Waffle and VRaptor (that verge on the transparent) and the compelling Grails. SOAP and REST designs could also benefit.
Paranamer allows you to generate and use parameter name info for versions of Java prior to JDK 5.0 and above. Parameter name access was scheduled for JDK 6.0, but was cancelled at a late stage as the spec-lead suggested the development team ran out of time to implement it. It didn't ship in JDK 7.0 either, though it did in JDK 8 (see below). Historically, it was felt that applications could end up depending on parameter names, and that they essentially became part of constructor/method signatures and could never be changed if you wanted to be backwards compatible. The view of the authors of Paranamer is that you should be aware that parameter names may change between releases, and code to not depend on them.
Paranamer is Open Source, and licensed as BSD, and first created in in July 2006. It is compatible with commercial/proprietary, GPL, BSD, and Apache (or any open/free source) use.
Java8 has parameter name access built in!
Paranamer is gaining JDK 8 compatibility. JDK 8 though has native support though, and stackoverflow shows you how to make that work.
Accessing Parameter Name data
There is a method called lookupParameterNames that returns an array of strings for a method or constructor.
// MySomethingOrOther.java**
Method method = Foo.class.getMethod(...);
Paranamer paranamer = new CachingParanamer();
String[] parameterNames = paranamer.lookupParameterNames(method) // throws ParameterNamesNotFoundException if not found
// or:
parameterNames = paranamer.lookupParameterNames(method, false) // will return null if not found
Paranamer does not have any runtime jar dependencies while looking up parameter info previously generated that's been zipped into a jar.
DefaultParanamer
DefaultParanamer tries to read parameter name data that JDK9 can compile in if you pass -paramaters to Javac. For maven:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgument>-parameters</compilerArgument>
</configuration>
</plugin>
LegacyParanamer
DefaultParanamer tries to read parameter name data from an extra public static field called __PARANAMER_DATA on the class. This field need to be added after compilation of the class, and before you put the resulting classes in a jar.
The static field essentially looks like the following. You really do not need to know this unless your going to make something compatible with Paranamer:
public static final String __PARANAMER_DATA = "v1.0 \n"
+ "<init> com.example.PeopleService peopleService \n"
+ "setName java.lang.String,java.lang.String givenName,familyName \n";
+ "setDateOfBirth int,int,int day,month,year \n";
Clearly the method's source needs to be analysed and lines added per method to that __PARANAMER_DATA field. See below.
BytecodeReadingParanamer
If generating meta data for parameter names at compile time is not for you, try class BytecodeReadingParanamer as a runtime only solution. This uses a cut down forked and cut-down version of ASM to extract debug information from a class at runtime. As it happens this is the fallback implementation for CachingParanamer when DefaultParanamer reports that there is no meta data for a class.
Note: BytecodeReadingParanamer does not work parameters stored in interfaces, because the javac compiler ALWAYS omits that information from the debug tables in the .class file.
JavadocParanamer
Pulls its parameter names from a Javadoc zip/jar (named in the constructor). Courtesy of Sam Halliday
PositionalParanamer
Numbers it's parameter names arg0, arg1, arg2 (etc), intended as a fall-back if you need it. From Stefan Fleiter.
AnnotationParanamer
AnnotationParanamer uses the @Named annotation from JSR 330 and extracts names pertinent to parameters from that.
public static class Something {
public void doSomething(@Named("usedName") String ignoredName) {
}
}
AnnotationParanamer takes a delegate paranamer instance as an optional constructor arg. This will allow constructors and methods to only partly leverage @Named, with other parameters having non-annotated parameter names (the via say DefaultParanamer or BytecodeReadingParanamer).
If you have an alternate annotation to @Named, then you can specify that in a subclass of AnnotationParanamer that overrides two methods isNamed and getNamedValue. Your overridden methods should do the equivalent of 'return an instance of Named' and return ((Named) ann).value(); respectively.
If you are using @Named annotation, you will need to add javax.atinject artifact in your classpath. Paranamer is built with the javax.atinject module as an optional dependency.
AdaptiveParanamer
AdaptiveParanamer is designed for using a series of Paranamer implementations together. The first supplied is asked if it can supply parameter name data for a constructor/method. If it cannot, then the next one is asked and so on. The default constructor for this uses DefaultParanamer with ByteCodeReadingParanamer as its contingency.
CachingParanamer
CachingParanamer stores the results of each parameter name lookup, so that second and subsequent invocations will be far quicker.
There's a subclass of CachingParanamer called CachingParanamer.WithoutWeakReferences. It does not use a WeakHashMap as an internal implementation. If you're great with profiling of applications under load, you might be able to justify use of this implementation for your particular app.
Feeding DefaultParanamer
Generating __PARANAMER_DATA with Ant
This for DefaultParanamer usage of course, as BytecodeReadingParanamer does not need it.
You need to download:
- latest paranamer jar
- latest paranamer-generator jar
- latest paranamer-ant jar
- latest qdox jar (1.8 or above)
... and declare in your Ant script the following after <javac/> (remember to add to the taskdef classpath all the above jars):
<taskdef name="paranamer"
classname="com.thoughtworks.paranamer.ant.ParanamerGeneratorTask"/>
<paranamer sourceDirectory="src/java" outputDirectory="target/classes"/>
Classes are changed to have an extra static String member variable that contains the member functions and their parameter names. Be sure to zip them up in to you final jar.
Generating __PARANAMER_DATA with Maven 2 or 3
For Maven, configuration is simpler. Just add this to the build/plugins section of your pom.xml:
<plugin>
<groupId>com.thoughtworks.paranamer</groupId>
<artifactId>paranamer-maven-plugin</artifactId>
<executions>
<execution>
<id>run</id> <!-- id is optional -->
<configuration>
<sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
</configuration>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<dependencies>
<!-- if some of parameter names you need to retain are held in pre-existing jars, they need to be added to the classpath -->
<dependency>
<groupId>some-artifact-group</groupId>
<artifactId>some-artifact</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</plugin>
The classes in the ultimate jar file will automatically be made with parameter name data.
Embedding Paranamer in your jar
There are already too many jar's for day to day Java development right? Simply consume the runtime Paranamer jar into your project's jar using the Maven2 'shade' plugin.
<!-- Put in your POM.xml file -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactId>artifact-shaded</shadedArtifactId>
<relocations>
<relocation>
<pattern>com.thoughtworks.paranamer</pattern>
<shad
Related Skills
node-connect
337.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
337.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.2kCommit, push, and open a PR

