我的目標是在每個基本代碼塊的開頭插入一點工具代碼。 Javaassist的ControlFlow.Block和CtMethod.insertAt()似乎是一個相當簡單的任務。下面是代碼中的相關塊到目前爲止(它位於轉換功能):Javassist的CtMethod.insertAt(line,src)工具代碼位於錯誤的字節碼位置
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)
的「行」參數是源代碼線位置,而不是字節碼線位置。在源代碼中,一些基本塊報告相同的行號!下面是輸出:
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)?