我正在进行Java字节码分析。我想继续跟踪局部变量的每个变化状态。这个想法很像一个调试器。例如,我有一个像
这样的Java源代码# get a column named region, with the names of the regions
df = get_admin1_regions("dominican republic")
df$value = 1:nrow(df) # add a column called "value"
# ?admin1_choropleth needs the name of the country and the data
admin1_choropleth(country.name = "dominican republic", df = df)
通过使用ASM 5.0,我可以访问行号,本地变量名,mehtod名,var指令等。访客看起来如下
public class Foo {
public void main() {
printOne();
}
public void printOne() {
int i=11110;
String hello="hello";
}
问题是我在哪里注入一个跟踪器(只是一个静态方法调用),并在堆栈上查找变量值并作为参数传递给跟踪器?
@Override
public void visitLineNumber(int line, Label start) {
System.out.println("line: "+line+" ");
mv.visitLineNumber(line, start);
}
@Override
public void visitLocalVariable(String name, String desc,String signature, Label start, Label end, int index) {
System.out.println("local variable:"+name);
mv.visitLocalVariable(name, desc, signature, start, end, index);
}
@Override
public void visitVarInsn(int opcode, int var) {
System.out.println("var instruction"+Integer.toHexString(opcode));
mv.visitVarInsn(opcode, var);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
System.out.println("method");
mv.visitMethodInsn(opcode, owner, name, desc, itf);
}
答案 0 :(得分:2)
你不能对访客做你想做的事。访问者只访问局部变量的声明,存储在类文件LocalVariableTable
属性的可选Code
属性中(请参阅specification here)。这为您提供了局部变量的签名,但没有告诉您在运行时它们的值发生了什么。为此,您需要分析字节码中的load
和store
指令(以及其他指令),正如您所说的那样,它将有效地编写调试器。
原则上,您可以访问代码,查找存储到您感兴趣的本地变量索引中的所有操作码,并插入检测代码以将新值传递给您自己的某些报告方法,但这将是一个重新实现调试器已经完成的工作很多。
重申:LocalVariableTable
不包含值。它是元数据描述局部变量 - 它们的名称,类型等 - 存储在类文件中以利于调试器。它是一个可选属性,仅在编译时包含调试信息时才会创建。在运行时,执行代码不使用LocalVariableTable
。局部变量值本身存在于堆栈中,在运行时分配。我认为你需要退一步思考你想要实现的目标。您想知道局部变量在运行时采用的值。 直到运行时才能知道。
您不能将调试器指向类文件并询问“局部变量x的值是多少?”。该类信息不存在于类文件中。这甚至都不是一个有意义的问题。您必须运行该程序才能在其上使用调试器。调试器暂停执行并在特定时间点查看执行堆栈上的值。您的asm访问者类正在查看类文件,而不是正在运行的代码或执行堆栈。
可以知道的内容,是运行时局部变量值在堆栈上的位置的索引。这是传递给本地变量visitor的索引参数。您需要获取该索引参数并分析方法的字节码,以查找将值存储到该索引处的变量中的所有操作码。这些代表方法中可能改变局部变量值的点。然后,您可以插入其他字节码来调用您自己的报告方法,并在指定的索引处传递局部变量的值。然后,您必须运行已检测的代码。毋庸置疑,这一切都不适合胆小的人!