(编辑:删除了之前的两个答案,一个用于回答编辑之前的问题,另一个是(如果不是绝对错误的话)至少接近该问题。)
如果使用(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; //Method java/lang/Object."<init>":()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."<init>":()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;
}
该虚拟机规范解释了我们现在看到的:
§4.7.9 LocalVariableTable
属性:
该LocalVariableTable
属性是Code
(§4.7.3)属性的可选可变长度属性。调试器可以使用它来确定方法执行期间给定局部变量的值。
将LocalVariableTable
变量的名称和类型存储在每个插槽中,因此可以将它们与字节码进行匹配。这就是调试器可以执行“评估表达式”的方式。
但是,正如埃里克森所说,无法通过正常反射访问该表。如果您仍然决心这样做,那么我相信Java平台调试器体系结构(JPDA)会有所帮助(但我自己从未使用过)。