Preserving parameter/argument names in compiled java classes

16,766

Solution 1

To preserve names in the class file for debugging purposes try project properties, Java compiler, then "Add variable attributes to generated class files" (See Eclipse Help).

Compiling the following source:

public class StackOverflowTest {
    public void test(String foo, String bar) {
        // blah
    }
}

Is decompiled into:

// Compiled from StackOverflowTest.java (version 1.5 : 49.0, super bit)
public class StackOverflowTest {

    // Method descriptor #6 ()V
    // Stack: 1, Locals: 1
    public StackOverflowTest();
        0  aload_0 [this]
        1  invokespecial java.lang.Object() [8]
        4  return
        Line numbers:
            [pc: 0, line: 1]
        Local variable table:
            [pc: 0, pc: 5] local: this index: 0 type: StackOverflowTest

    // Method descriptor #15 (Ljava/lang/String;Ljava/lang/String;)V
    // Stack: 0, Locals: 3
    public void test(java.lang.String foo, java.lang.String bar);
        0  return
        Line numbers:
            [pc: 0, line: 4]
        Local variable table:
            [pc: 0, pc: 1] local: this index: 0 type: StackOverflowTest
            [pc: 0, pc: 1] local: foo index: 1 type: java.lang.String
            [pc: 0, pc: 1] local: bar index: 2 type: java.lang.String
}

See the parameter names are preserved in the class files.

I would suggest you look into how your source is being compiled, which version it is compiled for etc.

EDIT:

Ah, I see this is different for interfaces - they don't seem to have this information available for the debugger which I guess makes sense. I don't think there'll be a way round this, if you just want to see the parameter names when you're editing source you'll need to go the javadoc route as Nagrom_17 suggests (attach the source).

Solution 2

You don't specially need the source to make arg names appear in Eclipse...If you specify the Javadoc, Eclipse will display the args.

Solution 3

It might help to compile with debug support, which stores all names in the .class file.

though I don't know whether Eclipse takes that into account.

Solution 4

There is no support in the class file data structure for storing the parameter names to any method, no matter what javac options you use.

In order to see the original names in an IDE you have to supply them with either the javadoc or the source.

If you have a particular need to get at them at runtime it is possible to add annotations to parameters, but you'll have to create your own as there isn't a standard set to use.

Sorry can't be more helpful

EDIT: I stand completely corrected...the class file format does clearly have space for named parameters (JLS 4.7)

What I can't see is how the hell you can get at them using java.lang.reflect.*

Solution 5

Eclipse will pick up the names of arguments if you include debug information in the class file: javac -g:vars should be enough.

Share:
16,766

Related videos on Youtube

Lena Schimmel
Author by

Lena Schimmel

I've been programming since I was 6 years. Currently, I'm doing a masters degree in computer science with focus on distributed system and information systems. Until 2009 I was doing a Bachelor of Science in "Medieninformatik", which is a funny thing in between computer science and media design. My main interests are: How to become an even better programmer Writing code that survives changes both in functional requirements and in the used platform Inventing something better than the crappy semantic web I'm frequently switching between Java and C++ as you can see by a look at my questions and tags.

Updated on April 15, 2022

Comments

  • Lena Schimmel
    Lena Schimmel about 2 years

    When I compile something like this:

    public class MyClass
    {
        void myMethod(String name, String options, String query, String comment)
        {
            ...
        }
    }
    

    and compile this to a class file, it seems that argument names are lost. That is, when some other Java code references MyClass and wants to call or overwrite myMethod, my IDE (currently Eclipse) seems to get this method signature from the class-file:

    void myMethod(String arg0, String arg1, String arg2, String arg3);
    

    I know that Eclipse (and possibly other IDEs too) allows me to provide a link to the source or the javadoc (as Bishiboosh pointed out) of MyClass and can take advantage of this. But I'm curious if there is some way to tell javac to include the names into the class-file, so that users of that class can see the argument names even if they only have the class file.

    Solution for classes

    When I compile a class with java -g:vars, the names of parameters are included in the class file. -g:vars seems to be equivalent to Eclipse -> project properties -> Java compiler -> Add variable attributes to generated class files.

    This solution was suggested by several authors, but the answer from Nick finally made me believe.

    On my machine, Eclipse sometimes used this info, sometimes it didn't, which was probably my fault or a bug in Eclipse, but not a problem with the class files or the compile. Anyway, now I know that the information is definitely present.

    But no solution for interfaces

    While this works (kind of) fine for classes, it's not working for interfaces.

    For me, the logical reason seems to be, that -g:vars only provides the names of local variables, which is what the documentation for javac also states. In the body of a method, it's parameters are very similar to local variables, thus they are covered by -g:vars. interface methods don't have bodies, so they can't have local varibles.

    My initial question only asked for classes, because I was not aware that there might be any difference.

    Class file format

    As gid pointed out, the class file format does not support storrage of parameter names. I found a section in the class file spec that descibes a data struture which should holf the parameter names of methods, but this is definitely not used when compiling interfaces.

    When compiling a class, I can't tell if the mentioned data structure is used, or if Eclipse infers the parameter names from the usage of parameters inside the method body. An expert could clarify this, but it's not that relevant I think.

  • Lena Schimmel
    Lena Schimmel almost 15 years
    That solution works for me, thanks. Anyway, I'd be interested if it is possible to have information about parameter names stored in the class file.
  • Lena Schimmel
    Lena Schimmel almost 15 years
    I'm currently compiling with source,lines,vars and Eclipse does not see the argument names. I'll double check if there is something wrong with my ant script, maybe the debug level is lost on the way from ant to javac...
  • Salandur
    Salandur almost 15 years
    javadocs are not compiled in the resulting class-files, but you can generate a site with the javadocs.
  • Pool
    Pool almost 15 years
    Yes, try project properties, Java compiler, then "Add variable attributes to generated class files". This should preserve the parameter names.
  • Lena Schimmel
    Lena Schimmel almost 15 years
    I haven't read the class file spec, but from what I can see, this seems to be true.
  • Gareth Davis
    Gareth Davis almost 15 years
    it's also the reason given by the groovy for not supporting named parameters
  • Lena Schimmel
    Lena Schimmel almost 15 years
    Just changed my mind. java.sun.com/docs/books/jvms/second_edition/html/… seems to describe that data structure as existing. Anyway, my class files do not contain this information, no matter what debug setting I use for javac.
  • Lena Schimmel
    Lena Schimmel almost 15 years
    Sorry, I was a bit confusing (or confused) with classes and interfaces. What you say seems to be true when applied to classes (which I asked for in my initial question) but is not true for interfaces. I've added some information to my question to reflect that.
  • Lena Schimmel
    Lena Schimmel almost 15 years
    As I added to my question text, -g:vars adds some information for classes, but no information for interfaces. And in both cases, Eclipse does not use this information.
  • Pool
    Pool almost 15 years
    The parameter names are preserved in the class file.
  • Aaron Digulla
    Aaron Digulla almost 15 years
    Please double check that the class file contains debug information. Maybe you've found a bug in Eclipse. I also noticed that Eclipse sometimes doesn't pick up argument names but I haven't really bothered to check why.
  • randers
    randers about 8 years
    Also, there is no need to write @return void - I think it even goes against the spec.