java-callgraph
Changes
pom.xml 6(+3 -3)
Details
pom.xml 6(+3 -3)
diff --git a/pom.xml b/pom.xml
index 561b57e..03c8154 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,9 +23,9 @@
<scope>compile</scope>
</dependency>
<dependency>
- <groupId>asm</groupId>
- <artifactId>asm-all</artifactId>
- <version>3.3</version>
+ <groupId>org.apache.bcel</groupId>
+ <artifactId>bcel</artifactId>
+ <version>5.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
diff --git a/src/main/java/gr/gousiosg/callgraph/ClassVisitor.java b/src/main/java/gr/gousiosg/callgraph/ClassVisitor.java
new file mode 100644
index 0000000..347230a
--- /dev/null
+++ b/src/main/java/gr/gousiosg/callgraph/ClassVisitor.java
@@ -0,0 +1,34 @@
+package gr.gousiosg.callgraph;
+
+import org.apache.bcel.classfile.EmptyVisitor;
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.MethodGen;
+
+public class ClassVisitor extends EmptyVisitor {
+
+ JavaClass visitedClass;
+ private ConstantPoolGen cp;
+
+ public ClassVisitor(JavaClass jc) {
+ visitedClass = jc;
+ cp = new ConstantPoolGen(visitedClass.getConstantPool());
+ }
+
+ public void visitJavaClass(JavaClass jc) {
+ Method[] methods = jc.getMethods();
+ for (int i = 0; i < methods.length; i++)
+ methods[i].accept(this);
+ }
+
+ public void visitMethod(Method method) {
+ MethodGen mg = new MethodGen(method, visitedClass.getClassName(), cp);
+ MethodVisitor visitor = new MethodVisitor(mg, visitedClass);
+ visitor.start();
+ }
+
+ public void start() {
+ visitJavaClass(visitedClass);
+ }
+}
diff --git a/src/main/java/gr/gousiosg/callgraph/JCallGraph.java b/src/main/java/gr/gousiosg/callgraph/JCallGraph.java
index 1e22617..6ef87f5 100644
--- a/src/main/java/gr/gousiosg/callgraph/JCallGraph.java
+++ b/src/main/java/gr/gousiosg/callgraph/JCallGraph.java
@@ -3,7 +3,8 @@ package gr.gousiosg.callgraph;
import java.io.IOException;
-import org.objectweb.asm.ClassReader;
+import org.apache.bcel.classfile.ClassParser;
+
/**
* Constructs a callgraph out of a JAR archive. Can combine multiple archives
@@ -15,12 +16,14 @@ import org.objectweb.asm.ClassReader;
public class JCallGraph {
public static void main(String[] args) {
+ ClassParser cp;
try {
- ClassPrinter cp = new ClassPrinter();
- ClassReader cr = new ClassReader("java.lang.Thread");
- cr.accept(cp, 0);
+ cp = new ClassParser("/Volumes/Files/Developer/java-callgraph/target/classes/gr/gousiosg/callgraph/ClassVisitor.class");
+ ClassVisitor visitor = new ClassVisitor(cp.parse());
+ visitor.start();
} catch (IOException e) {
-
+ // TODO Auto-generated catch block
+ e.printStackTrace();
}
- }
+ }
}
diff --git a/src/main/java/gr/gousiosg/callgraph/MethodVisitor.java b/src/main/java/gr/gousiosg/callgraph/MethodVisitor.java
new file mode 100644
index 0000000..1d55bf2
--- /dev/null
+++ b/src/main/java/gr/gousiosg/callgraph/MethodVisitor.java
@@ -0,0 +1,107 @@
+package gr.gousiosg.callgraph;
+
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.generic.ArrayInstruction;
+import org.apache.bcel.generic.CHECKCAST;
+import org.apache.bcel.generic.CodeExceptionGen;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.ConstantPushInstruction;
+import org.apache.bcel.generic.EmptyVisitor;
+import org.apache.bcel.generic.FieldInstruction;
+import org.apache.bcel.generic.INSTANCEOF;
+import org.apache.bcel.generic.Instruction;
+import org.apache.bcel.generic.InstructionConstants;
+import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.InvokeInstruction;
+import org.apache.bcel.generic.LocalVariableInstruction;
+import org.apache.bcel.generic.MethodGen;
+import org.apache.bcel.generic.ReturnInstruction;
+import org.apache.bcel.generic.Type;
+
+public class MethodVisitor extends EmptyVisitor {
+
+ JavaClass visitedClass;
+ private MethodGen mg;
+ private ConstantPoolGen cp;
+
+ public MethodVisitor(MethodGen m, JavaClass jc) {
+ visitedClass = jc;
+ mg = m;
+ cp = mg.getConstantPool();
+ }
+
+ public void start() {
+ if (!mg.isAbstract() && !mg.isNative()) {
+ for (InstructionHandle ih = mg.getInstructionList().getStart(); ih != null; ih = ih.getNext()) {
+ Instruction i = ih.getInstruction();
+
+ if (!visitInstruction(i))
+ i.accept(this);
+ }
+ updateExceptionHandlers();
+ }
+ }
+
+ /** Visit a single instruction. */
+ private boolean visitInstruction(Instruction i) {
+ short opcode = i.getOpcode();
+
+ return ((InstructionConstants.INSTRUCTIONS[opcode] != null)
+ && !(i instanceof ConstantPushInstruction) && !(i instanceof ReturnInstruction));
+ }
+
+ /** Local variable use. */
+ public void visitLocalVariableInstruction(LocalVariableInstruction i) {
+ //if (i.getOpcode() != Constants.IINC)
+ //cv.registerCoupling(i.getType(cp));
+ }
+
+ /** Array use. */
+ public void visitArrayInstruction(ArrayInstruction i) {
+ //cv.registerCoupling(i.getType(cp));
+ }
+
+ /** Field access. */
+ public void visitFieldInstruction(FieldInstruction i) {
+ //cv.registerFieldAccess(i.getClassName(cp), i.getFieldName(cp));
+ //cv.registerCoupling(i.getFieldType(cp));
+ }
+
+ /** Method invocation. */
+ public void visitInvokeInstruction(InvokeInstruction i) {
+ System.out.println(visitedClass.getClassName() + ":" + mg.getName() + "->" + i.getReferenceType(cp) + ":"+ i.getMethodName(cp));
+ //Type[] argTypes = i.getArgumentTypes(cp);
+ //for (int j = 0; j < argTypes.length; j++)
+ // cv.registerCoupling(argTypes[j]);
+ //cv.registerCoupling(i.getReturnType(cp));
+ /* Measuring decision: measure overloaded methods separately */
+ //cv.registerMethodInvocation(i.getClassName(cp), i.getMethodName(cp),
+ // argTypes);
+ }
+
+ /** Visit an instanceof instruction. */
+ public void visitINSTANCEOF(INSTANCEOF i) {
+
+ }
+
+ /** Visit checklast instruction. */
+ public void visitCHECKCAST(CHECKCAST i) {
+
+ }
+
+ /** Visit return instruction. */
+ public void visitReturnInstruction(ReturnInstruction i) {
+ }
+
+ /** Visit the method's exception handlers. */
+ private void updateExceptionHandlers() {
+ CodeExceptionGen[] handlers = mg.getExceptionHandlers();
+
+ /* Measuring decision: couple exceptions */
+ for (int i = 0; i < handlers.length; i++) {
+ Type t = handlers[i].getCatchType();
+ //if (t != null)
+ //cv.registerCoupling(t);
+ }
+ }
+}