如何列出Java方法/函数中的所有本地变量?

8
我的主要问题是:我知道可以通过反射通用地输出类字段,即使您不知道变量名称、类型或甚至数量。然而,是否有一种方法可以列出当前函数或当前范围内的所有变量,假设我不知道变量名字是什么?
换句话说:
int x = 5;
int y = 42;
// some more code
//Now I want to println x and y, but assuming I cannot use "x" or "y".

我也很乐意回答这个问题: 假设我可以存储所有变量的名称,这对解决问题有帮助吗?例如:

Set<String> varNames = new HashSet<String>();
int x = 5;
varNames.add("x");
int y = 42;
varNames.add("y");
// some more code
//Now with varNames, can I output x and y without using "x" or "y"?

为什么我在问这个问题?我正在使用ANTLR将XYZ语言翻译成Java,并且我想提供一种简单的方法,在任何时间点输出程序的整个状态。
第三种可能的解决方案:如果Java不支持该功能,是否有办法编写字节码以访问调用函数并检查堆栈?这也可以解决问题。
如果Java具有类似于Python的eval()或PHP的get_defined_vars()的等效功能,那将是非常棒的。
如果这有所区别,我使用的是Java 6,但适用于Java 5、6或7的任何内容都应该是好的。
谢谢!

也许这个问题相关(https://dev59.com/dU7Sa4cB1Zd3GeqP1CMw) - user1406062
2个回答

5
据我所知,通常情况下,您无法使用普通的Java代码来访问当前堆栈帧中的局部变量。如果您能在运行字节码之前通过某种后处理器运行它,并假设您仍然包含调试符号,则可以自动生成相应的代码来实现该功能,但我不认为有任何一种反射方式可以访问当前堆栈帧中的局部变量。

有趣。像 Eclipse 调试器这样的工具是如何检查堆栈的呢?它需要通过本地网络管道连接到 JVM,还是在可以访问程序内存的线程中运行? - Arcymag
@Arcymag - 我认为调试器不需要检查堆栈;它依赖于在编译时创建的符号文件(或类似文件)。 - Richard JP Le Guen

1

如果您不想将此作为程序正常执行路径的一部分,而只是用于调试,则可以使用Java平台调试架构(JPDA)。实质上,您将编写自己的调试器,设置断点并使用JDI API查询程序状态。局部变量可以使用StackFrame#visibleVariables()列出。

如果以上不是一个选项,那么将非常难以实现。要获取变量名称,您可以解析类文件并读取方法的本地变量表属性。但是,获取局部变量的值的唯一方法是通过aload/iload等字节码指令。这些必须存在于您要分析的方法中,因此您无法将此功能放入不同的辅助方法中。


你能告诉我在哪里可以找到JPDA的示例以及活跃的在线社区吗? - WSS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接