(编辑:删除了两个之前的回答,一个是回答修改前的问题,另一个虽然不完全错误,但至少接近错误。)
如果你使用调试信息进行编译(javac -g
),本地变量的名称将保存在 .class 文件中。例如,考虑这个简单的类:
class TestLocalVarNames {
public String aMethod(int arg) {
String local1 = "a string";
StringBuilder local2 = new StringBuilder();
return local2.append(local1).append(arg).toString();
}
}
使用javac -g:vars TestLocalVarNames.java
编译后,局部变量的名称现在在.class文件中。可以使用javap
命令的-l
选项(“打印行号和局部变量表”)来显示它们。
javap -l -c TestLocalVarNames
显示:
class TestLocalVarNames extends java.lang.Object{
TestLocalVarNames();
Code:
0: aload_0
1: invokespecial #1;
4: return
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LTestLocalVarNames;
public java.lang.String aMethod(int);
Code:
0: ldc #2;
2: astore_2
3: new #3;
6: dup
7: invokespecial #4;
10: astore_3
11: aload_3
12: aload_2
13: invokevirtual #5;
16: iload_1
17: invokevirtual #6;
20: invokevirtual #7;
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;
}
VM规范解释了我们在这里看到的内容:
§4.7.9 LocalVariableTable
属性:
LocalVariableTable
属性是一个可选的变长属性,属于 Code
(§4.7.3) 属性。调试器可以使用它来确定方法执行期间给定局部变量的值。
LocalVariableTable
存储每个位置上变量的名称和类型,因此可以将它们与字节码进行匹配。这就是调试器如何进行“表达式求值”的方式。
不过正如 erickson 所说,没有办法通过正常反射访问该表格。如果您仍然决心要这样做,我相信Java平台调试体系结构(JPDA)将有所帮助(但我自己从未使用过)。