Extracting basic blocks information from Java Bytecodes
I was looking for some way to extract the basic block information from Java bytecodes, when I found the Javassist library. According to the Javassist website
Following is simple example, showing how to use it. Our objective here is to find basic block information in an method, in a given class file. A basic block can be described as a portion of code with a single entry and exit point. This implies that if the execution enters a basic block, all the instruction in that basic block would be executed.
I downloaded Javassist from the following website :
http://sourceforge.net/projects/jboss/files/Javassist/3.18.0-GA/
I downloaded Javassist from the following website :
http://sourceforge.net/projects/jboss/files/Javassist/3.18.0-GA/
So first we need a class, which we wish to study. I used the following class file.
public class SampleCode {
private int varA;
private int varB;
private int toggle;
private int result;
public SampleCode() {
super();
this.varA = 0;
this.varB = 0;
this.toggle = 0;
this.result = -1;
}
public void setVarA(int varA) {
this.varA = varA;
}
public void setVarB(int varB) {
this.varB = varB;
}
public void setToggle(int toggle) {
this.toggle = toggle;
}
public int calculate(){
if(toggle==1){
result = varA * varA + varB;
}else{
result = varA + varB;
}
return result;
}
}
Now to extract the basic block, we can use the following class file
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.bytecode.BadBytecode;
import javassist.bytecode.analysis.ControlFlow;
import javassist.bytecode.analysis.ControlFlow.Block;
import static javassist.ClassPool.getDefault;
public class BasicBlockExtractor {
public static final String CLASSNAME = "SampleCode";
public static final String METHODNAME_1 = "calculate";
public static final String METHODNAME_2 = "setVarA";
public static void main(String[] args) throws NotFoundException, BadBytecode {
extractBasicBlocks();
}
public static void extractBasicBlocks() throws NotFoundException, BadBytecode{
//Get the Class implementation byte code
CtClass ctClass = getDefault().get(CLASSNAME);
//Get the method from the Class byte code
CtMethod ctmethod = ctClass.getDeclaredMethod(METHODNAME_1);
ControlFlow cf = new ControlFlow(ctmethod);
Block[] blocks = cf.basicBlocks();
System.out.println("Number of basic blocks in class ' "+ CLASSNAME + " ' in method ' " + METHODNAME_1 + " ' is " + blocks.length);
}
}
You must add the Javassist jar file to you project, for this to work. Execution the above code gives the following output
"Number of basic blocks in class ' SampleCode ' in method ' calculate ' is 4"
Subsequently, if you wish to obtain the line numbers for different basic blocks in a method you could do it as follows :-
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.bytecode.BadBytecode;
import javassist.bytecode.analysis.ControlFlow;
import javassist.bytecode.analysis.ControlFlow.Block;
import static javassist.ClassPool.getDefault;
public class BasicBlockExtractor{
public static final String CLASSNAME = "SampleCode";
public static final String METHODNAME_1 = "calculate";
public static final String METHODNAME_2 = "setVarA";
public static void main(String[] args) throws NotFoundException, BadBytecode, CannotCompileException {
extractBasicBlocks();
}
public static void extractBasicBlocks() throws NotFoundException, BadBytecode, CannotCompileException{
//Get the Class implementation byte code
CtClass ctClass = getDefault().get(CLASSNAME);
//Get the method from the Class byte code
CtMethod ctmethod = ctClass.getDeclaredMethod(METHODNAME_1);
ControlFlow cf = new ControlFlow(ctmethod);
Block[] blocks = cf.basicBlocks();
System.out.println("Number of basic blocks in class ' "+ CLASSNAME + " ' in method ' " + METHODNAME_1 + " ' is " + blocks.length);
for(Block thisbb : blocks){
int pos=ctmethod.getMethodInfo().getLineNumber(thisbb.position()); //Source code line position from binary line position
System.out.println("Basic block "+thisbb.index() +" is at "+pos);
}
}
}
For me, the output of the above code was as follows :-
Number of basic blocks in class ' SampleCode ' in method ' calculate ' is 4
Basic block 0 is at 35
Basic block 1 is at 36
Basic block 2 is at 38
Basic block 3 is at 41
No comments:
Post a Comment