我有一个像这样的简单程序:
package tests;
import java.util.Scanner;
public class TestSum {
public static void main(String[] args) {
int sum = 0;
System.out.print("Please enter starting i: ");
int i = new Scanner(System.in).nextInt();
while ( i < 11 ) {
sum = sum + i;
i = i + 1;
}
System.out.println("sum = " + sum);
System.out.println("Ending i = " + i);
}
}
我将它构建到一个jar文件中,我想使用WALA添加更多的检测源代码来计算循环执行次数,以便进行动态分析。
这就是我使用Wala所做的事情,大部分内容都来自这个例子Wala Bench Example
import com.ibm.wala.shrikeBT.*;
import com.ibm.wala.shrikeBT.analysis.Verifier;
import com.ibm.wala.shrikeBT.shrikeCT.CTDecoder;
import com.ibm.wala.shrikeBT.shrikeCT.ClassInstrumenter;
import com.ibm.wala.shrikeBT.shrikeCT.OfflineInstrumenter;
import com.ibm.wala.shrikeCT.ClassWriter;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintStream;
import java.io.Writer;
/**
* Created by quocnghi on 2/2/17.
*/
public class InstrumentedTest {
private final static boolean disasm = true;
private final static boolean verify = true;
private static OfflineInstrumenter instrumenter = new OfflineInstrumenter(true);
public static void main(String[] args) throws Exception {
for (int i = 0; i < 1; i++) {
Writer w = new BufferedWriter(new FileWriter("report", false));
args = instrumenter.parseStandardArgs(args);
instrumenter.setPassUnmodifiedClasses(true);
instrumenter.beginTraversal();
ClassInstrumenter ci;
while ((ci = instrumenter.nextClass()) != null) {
doClass(ci, w);
}
instrumenter.close();
}
}
static final String fieldName = "_Bench_enable_trace";
// Keep these commonly used instructions around
static final Instruction getSysOut = Util.makeGet(System.class, "out");
static final Instruction callPrintln = Util.makeInvoke(PrintStream.class, "println", new Class[]{String.class});
private static void doClass(final ClassInstrumenter ci, Writer w) throws Exception {
final String className = ci.getReader().getName();
System.out.println("Class name : " + className);
w.write("Class: " + className + "\n");
w.flush();
for (int m = 0; m < ci.getReader().getMethodCount(); m++) {
MethodData d = ci.visitMethod(m);
System.out.println(d.getName());
// d could be null, e.g., if the method is abstract or native
if (d != null) {
w.write("Instrumenting " + ci.getReader().getMethodName(m) + " " + ci.getReader().getMethodType(m) + ":\n");
w.flush();
if (disasm) {
w.write("Initial ShrikeBT code:\n");
(new Disassembler(d)).disassembleTo(w);
w.flush();
}
if (verify) {
Verifier v = new Verifier(d);
v.verify();
}
MethodEditor methodEditor = new MethodEditor(d);
methodEditor.beginPass();
final int noTraceLabel = methodEditor.allocateLabel();
IInstruction[] instr = methodEditor.getInstructions();
final String msg0 = "Loop called at " + Util.makeClass("L" + ci.getReader().getName() + ";") + "."
+ ci.getReader().getMethodName(m);
int i = 0;
for (IInstruction in : instr) {
if (in instanceof ConditionalBranchInstruction) {
int b = i;
methodEditor.insertBefore(i, new MethodEditor.Patch() {
@Override
public void emitTo(MethodEditor.Output w) {
w.emit(getSysOut);
w.emit(ConstantInstruction.makeString(msg0));
w.emit(callPrintln);
w.emitLabel(noTraceLabel);
}
});
}
i++;
System.out.println(in.toString());
}
methodEditor.applyPatches();
if (disasm) {
w.write("Final ShrikeBT code:\n");
(new Disassembler(d)).disassembleTo(w);
w.flush();
}
}
}
ClassWriter cw = ci.emitClass();
instrumenter.outputModifiedClass(ci, cw);
}
}
我希望在添加更多检测代码之后,程序应该变成这样,在循环中添加一行System.out.println:
包测试;
import java.util.Scanner;
public class TestSum {
public static void main(String[] args) {
int sum = 0;
System.out.print("Please enter starting i: ");
int i = new Scanner(System.in).nextInt();
while ( i < 11 ) {
sum = sum + i;
i = i + 1;
System.out.println("One count for this loop");
}
System.out.println("sum = " + sum);
System.out.println("Ending i = " + i);
}
}
但我收到了这个错误:
java.lang.ClassFormatError: StackMapTable format error: wrong attribute size