Skip to content

Instantly share code, notes, and snippets.

@pxpc2
Created April 7, 2013 19:55
Show Gist options
  • Save pxpc2/5332228 to your computer and use it in GitHub Desktop.
Save pxpc2/5332228 to your computer and use it in GitHub Desktop.
package us.brtm.cfg.generic;
import org.objectweb.asm.tree.analysis.*;
import java.util.HashSet;
import java.util.Set;
/**
* @author Pedro Daia Cardoso
*/
public class Node<V extends Value> extends Frame<V> {
private Set<Node<V>> successors = new HashSet<>();
public Node(Frame<? extends V> src) {
super(src);
}
public Node(int nLocals, int nStack) {
super(nLocals, nStack);
}
public Set<Node<V>> getSuccessors() {
return successors;
}
}
package us.brtm.cfg;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.*;
import us.brtm.cfg.generic.Node;
/**
* @author Pedro Daia Cardoso
*/
public class Graph {
/**
* The representation of the analyzed method.
*/
private MethodNode method;
/**
* The analyzer instance of an analyzed method :P
*/
private Analyzer<BasicValue> analyzer;
/**
* @param owner the internal name of the class to which the method belongs.
* @param method the method to be analyzed.
* @throws AnalyzerException if a problem occurs during the analysis.
*/
public Graph(String owner, MethodNode method) throws AnalyzerException {
this.method = method;
this.analyzer = new Analyzer<BasicValue>(new BasicInterpreter()) {
protected Frame<BasicValue> newFrame(int nLocals, int nStack) {
return new Node<>(nLocals, nStack);
}
protected Frame<BasicValue> newFrame(Frame<? extends BasicValue> src) {
return new Node<>(src);
}
protected void newControlFlowEdge(int src, int dst) {
Node<BasicValue> s = (Node<BasicValue>) getFrames()[src];
s.getSuccessors().add((Node<BasicValue>) getFrames()[dst]);
}
};
this.analyzer.analyze(owner, method);
}
/**
* Optimizes the method by removing useless things and/or
* simplifying the code.
*/
public void optimizeMethod() {
Frame<BasicValue>[] frames = analyzer.getFrames();
AbstractInsnNode[] instructions = method.instructions.toArray();
for (int i = 0; i < frames.length; i++) {
AbstractInsnNode instruction = instructions[i];
if (frames[i] == null && !(instruction instanceof LabelNode)) {
method.instructions.remove(instructions[i]);
}
}
}
/**
* A simple method to calculate the cyclomatic
* complexity of a method. This metric is defined
* as the number of edges in the control flow graph,
* minus the number of nodes, plus two.
* The metric gives a good indication if the complexity
* of a method, which have a relation with the average
* amount of bugs in the method.
*
* @return the cyclomatic complexity of this graph's method.
*/
public int getCyclomaticComplexity() {
Frame<BasicValue>[] frames = analyzer.getFrames();
int edges = 0;
int nodes = 0;
for (Frame<BasicValue> frame : frames) {
if (frame != null) {
edges += ((Node<BasicValue>) frame).getSuccessors().size();
nodes += 1;
}
}
return edges - nodes + 2;
}
/**
* @return returns the analyzer instance
*/
public Analyzer getAnalyzer() {
return analyzer;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment