我的目标是在每个基本代码块的开头插入一些检测代码。使用Javaassist的ControlFlow.Block和CtMethod.insertAt()似乎是一个相当简单的任务。这是迄今为止相关的代码块(它位于转换函数中):
ControlFlow flow=new ControlFlow(m); //m is the CtMethod currently being instrumented
Block[] blockArray=flow.basicBlocks();
for(Block thisbb : blockArray){
//Dynamically Update Method Statistics
String blockUpdate=new String();
String thisbbIndex=Integer.toString(thisbb.index());
blockUpdate+=mse+".setBlockIndex("+thisbbIndex+"); ";
blockUpdate="{ " + blockUpdate + "} ";
//Insert
int pos=m.getMethodInfo().getLineNumber(thisbb.position()); //Source code line position from binary line position
System.out.print("At "+pos+": "+blockUpdate);
int n=m.insertAt(pos, blockUpdate);
System.out.println(" -> "+n);
}
请注意CtMethod.insertAt(line,srcCode)
中的“line”参数是源代码行位置,而不是字节码行位置。在源代码中,一些基本块报告的是相同的行号!这是输出:
At 6: { _JDA_mse.setBlockIndex(0); } -> 6
At 8: { _JDA_mse.setBlockIndex(1); } -> 8
At 8: { _JDA_mse.setBlockIndex(2); } -> 8
At 8: { _JDA_mse.setBlockIndex(3); } -> 8
At 8: { _JDA_mse.setBlockIndex(4); } -> 8
At 8: { _JDA_mse.setBlockIndex(5); } -> 8
At 8: { _JDA_mse.setBlockIndex(6); } -> 8
At #
表示我请求放置代码的位置,-> #
表示源代码中实际插入的位置(如果一切正常,则应该是相同)。 { ... }
中的所有内容都是我想要放置的代码(_JDA_mse
是我使用Javassist方法添加到函数中的局部变量,因此使用它没有问题。)
问题是for(int i=0; i<size; ++i)
包含多个基本块,这些块在源代码中是不可分割的,但在字节码中明显不同。这就是为什么多个基本块被映射到同一源代码行的原因,它只是表明源代码行没有提供足够的仪表准确性来记录基本块。 有没有办法模拟CtMethod.insertAt(bytecodePosition,srcString)而不是使用提供的CtMethod.insertAt(sourceLine,srcString)?