Using Java Reflection, is it possible to get the name of a local variable? For example, if I have this:
Foo b = new Foo();
Foo a = new Foo();
Foo r = new Fo
(Edit: two previous answers removed, one for answering the question as it stood before edits and one for being, if not absolutely wrong, at least close to it.)
If you compile with debug information on (javac -g
), the names of local variables are kept in the .class file. For example, take this simple class:
class TestLocalVarNames {
public String aMethod(int arg) {
String local1 = "a string";
StringBuilder local2 = new StringBuilder();
return local2.append(local1).append(arg).toString();
}
}
After compiling with javac -g:vars TestLocalVarNames.java
, the names of local variables are now in the .class file. javap
's -l
flag ("Print line number and local variable tables") can show them.
javap -l -c TestLocalVarNames
shows:
class TestLocalVarNames extends java.lang.Object{
TestLocalVarNames();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LTestLocalVarNames;
public java.lang.String aMethod(int);
Code:
0: ldc #2; //String a string
2: astore_2
3: new #3; //class java/lang/StringBuilder
6: dup
7: invokespecial #4; //Method java/lang/StringBuilder."":()V
10: astore_3
11: aload_3
12: aload_2
13: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16: iload_1
17: invokevirtual #6; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
20: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
23: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 24 0 this LTestLocalVarNames;
0 24 1 arg I
3 21 2 local1 Ljava/lang/String;
11 13 3 local2 Ljava/lang/StringBuilder;
}
The VM spec explains what we're seeing here:
§4.7.9 The LocalVariableTable Attribute:
The
LocalVariableTable
attribute is an optional variable-length attribute of aCode
(§4.7.3) attribute. It may be used by debuggers to determine the value of a given local variable during the execution of a method.
The LocalVariableTable
stores the names and types of the variables in each slot, so it is possible to match them up with the bytecode. This is how debuggers can do "Evaluate expression".
As erickson said, though, there's no way to access this table through normal reflection. If you're still determined to do this, I believe the Java Platform Debugger Architecture (JPDA) will help (but I've never used it myself).