Re: [BCEL-info]Replacing instructions. (doh!)
Brought to you by:
dahm
|
From: Graham T. <Gra...@ci...> - 2003-03-18 21:12:24
|
>
>
>Don't know why you want to play ping-pong with comparison instructions;
>
>
To build a state-of-the-art mutation test system of course! =' )
I was basing my example on the tech. report, and had something similar
to the 'optimising boolean expressions' example. Using FindPattern, etc,
lead me to focus on methods, which resulted in nasty ClassGenExceptions.
(example below).
Using a ClassGen object, things now work a peach! I've included the
working code below to act as an example, so such dither-brained-ness
can be avoided!
Thanks for your help,
Graham.
Do do:
public class SimpleReplacement {
private static int mutCount = 0;
public static void main(String[] args) {
JavaClass clazz = Repository.lookupClass("TestClass");
ClassGen classGen = new ClassGen(clazz);
ConstantPoolGen constPoolGen = new ConstantPoolGen(
clazz.getConstantPool());
Method[] methods = classGen.getMethods();
int methodIndex = 0;
while (methodIndex < methods.length) {
Method method = methods[methodIndex];
MethodGen methodGen = new MethodGen(
method, clazz.getClassName(), constPoolGen);
InstructionList instList = methodGen.getInstructionList();
InstructionHandle[] handles = instList.getInstructionHandles();
int handleIndex = 0;
while (handleIndex < handles.length) {
InstructionHandle handle = handles[handleIndex];
Instruction inst = handle.getInstruction();
if (inst.getOpcode() == Constants.IF_ICMPEQ) {
System.out.println("We have an IF_ICMPEQ at inst "
+ handle.getPosition());
generateMutant(clazz, methodIndex, handleIndex);
}
++handleIndex;
}
++methodIndex;
}
System.out.println("DONE");
}
private static void generateMutant(JavaClass clazz, int methodIndex,
int handleIndex) {
ClassGen classGen = new ClassGen(clazz);
Method[] methods = classGen.getMethods();
String className = classGen.getClassName();
ConstantPoolGen constPoolGen = classGen.getConstantPool();
MethodGen methodGen = new MethodGen(
methods[methodIndex], className, constPoolGen);
InstructionList instList = methodGen.getInstructionList();
InstructionHandle[] handles = instList.getInstructionHandles();
InstructionHandle handle = handles[handleIndex];
IF_ICMPNE newInst = new IF_ICMPNE(
((IfInstruction)handle.getInstruction()).getTarget());
handle.setInstruction(newInst);
classGen.setMethodAt(methodGen.getMethod(), methodIndex);
System.out.println("new inst: " + handles[handleIndex]);
try {
classGen.getJavaClass().dump(
"H:\\quick_temp\\TestClass.class.mut_" + (++mutCount));
} catch (IOException e) {
e.printStackTrace();
}
}
}
Don't do:
public class SimpleReplacementBad {
public static void main(String[] args) {
int mutationCount = 0;
JavaClass clazz = Repository.lookupClass("TestClass");
Method[] theMethods = clazz.getMethods();
ConstantPoolGen cpg = new ConstantPoolGen(
clazz.getConstantPool());
for (int i = 0, n = theMethods.length; i < n; i++) {
MethodGen theMethodGen = new MethodGen(
theMethods[i], clazz.getClassName(), cpg);
InstructionList il = theMethodGen.getInstructionList();
FindPattern f = new FindPattern(il);
String pat = "(`IF_ICMPNE')";
InstructionHandle next = null;
for (InstructionHandle ih = f.search(pat);
ih != null;
ih = f.search(pat, next)) {
InstructionHandle theMatch = f.getMatch()[0];
System.out.println("match: " + theMatch + " in " +
theMethods[i]);
Instruction original = theMatch.getInstruction();
theMatch.setInstruction(new IF_ICMPEQ(
((IfInstruction)theMatch.getInstruction()).getTarget()));
theMethods[i] = theMethodGen.getMethod();
try {
clazz.dump("H:\\quick_temp\\mut_" +
(mutationCount++) + ".class");
} catch (IOException e) {
e.printStackTrace(); //To change body of catch
statement use Options | File Templates.
}
System.out.println("wrote to H:\\quick_temp\\mut_" +
mutationCount + ".class");
theMatch.setInstruction(original);
if ((next = theMatch.getNext()) == null) {
break;
}
}
il.dispose(); // Reuse instruction handles
}
System.out.println("done");
}
}
Results in:
match: 14: if_icmpne[160](3) -> iload_1 in public boolean plentyEQ(int i)
de.fub.bytecode.generic.ClassGenException: Target of if_icmpne[160](3)
is invalid null handle
at
de.fub.bytecode.generic.BranchInstruction.getTargetOffset(BranchInstruction.java:58)
at
de.fub.bytecode.generic.BranchInstruction.getTargetOffset(BranchInstruction.java:74)
at
de.fub.bytecode.generic.BranchInstruction.dump(BranchInstruction.java:44)
at
de.fub.bytecode.generic.InstructionList.getByteCode(InstructionList.java:930)
at de.fub.bytecode.generic.MethodGen.getMethod(MethodGen.java:555)
at SimpleReplacementBad.main(SimpleReplacementBad.java:44)
Exception in thread "main"
|