diff --git a/src/ch/usi/inf/sp/callgraph/CallGraphBuilder.java b/src/ch/usi/inf/sp/callgraph/CallGraphBuilder.java index 993abd1..78db08a 100644 --- a/src/ch/usi/inf/sp/callgraph/CallGraphBuilder.java +++ b/src/ch/usi/inf/sp/callgraph/CallGraphBuilder.java @@ -54,14 +54,16 @@ public final class CallGraphBuilder implements ClassAnalyzer { if (opCode == Opcodes.INVOKESTATIC || opCode == Opcodes.INVOKESPECIAL) { // target is static, no fancy search needed callSite.addPossibleTargetClass(clazz); // Cave Johnson, we're done here - } else if (opCode == Opcodes.INVOKEDYNAMIC) { + } else if (opCode == Opcodes.INVOKEVIRTUAL) { final Deque subClasses = new ArrayDeque<>(); subClasses.add(clazz); // BFS over class and subclasses and add them all as possible targets while (!subClasses.isEmpty()) { final ClassType subClazz = subClasses.pop(); - callSite.addPossibleTargetClass(subClazz); + if (!subClazz.isAbstract()) { + callSite.addPossibleTargetClass(subClazz); + } subClasses.addAll(subClazz.getSubTypes()); } } else { // opCode == Opcodes.INVOKEINTERFACE diff --git a/src/ch/usi/inf/sp/callgraph/renderer/DotGraph.java b/src/ch/usi/inf/sp/callgraph/renderer/DotGraph.java index 08e62b4..48ed32b 100644 --- a/src/ch/usi/inf/sp/callgraph/renderer/DotGraph.java +++ b/src/ch/usi/inf/sp/callgraph/renderer/DotGraph.java @@ -48,31 +48,25 @@ public class DotGraph { } private void scanMethods() { - final Deque methodQueue = new ArrayDeque<>(methodNodes.getAll()); - while (!methodQueue.isEmpty()) { - final DotMethodNode methodNode = methodQueue.pop(); - final Method m = methodNode.getMethodLike().getMethod(); + for (final DotMethodNode fromMethodNode : methodNodes.getAll()) { + final Method m = fromMethodNode.getMethodLike().getMethod(); if (m == null) continue; // we care about actual methods only, not callsites for (final CallSite c : m.getCallSites()) { final DotMethodNode toMethodNode = methodNodes.addIfNew(new DotMethodNode(new CallSiteAdapter(c))); - otherEdges.add(new InvokeEdge(methodNode, toMethodNode, c.getOpcode(), true)); + otherEdges.add(new InvokeEdge(fromMethodNode, toMethodNode, c.getOpcode(), true)); for (final ClassType p : c.getPossibleTargetClasses()) { - if (p.getInternalName().endsWith("Math")) { - System.out.println("aaa"); - } - - final DotMethodNode pm = methodNodes.addIfNew(new DotMethodNode(new PossibleTargetAdapter(c, p))); - final DotClassNode pc = classNodes.addIfNew(new DotClassNode(p)); + final DotMethodNode toPossibleMethodNode = methodNodes.addIfNew(new DotMethodNode(new PossibleTargetAdapter(c, p))); + otherEdges.add(new InvokeEdge(fromMethodNode, toPossibleMethodNode, c.getOpcode(), false)); // if the target is a new node, the class of that node might not have been analyzed, - // thus class to method edges might not have been added - classToMethodEdges.add(new ClassToMethodEdge(pc, pm)); + // thus class to method edges might not have been added. We re-add the class to method edge, and + // duplicates are handled by the Set collection. + final DotClassNode toPossibleClassNode = classNodes.addIfNew(new DotClassNode(p)); + classToMethodEdges.add(new ClassToMethodEdge(toPossibleClassNode, toPossibleMethodNode)); } - - otherEdges.add(new InvokeEdge(methodNode, toMethodNode, c.getOpcode(), false)); } } } diff --git a/src/ch/usi/inf/sp/callgraph/renderer/InvokeEdge.java b/src/ch/usi/inf/sp/callgraph/renderer/InvokeEdge.java index 70b42e7..0b4729a 100644 --- a/src/ch/usi/inf/sp/callgraph/renderer/InvokeEdge.java +++ b/src/ch/usi/inf/sp/callgraph/renderer/InvokeEdge.java @@ -57,4 +57,14 @@ public class InvokeEdge implements DotEdge { public DotMethodNode getTo() { return to; } + + @Override + public String toString() { + return "InvokeEdge{" + + "from=" + from.getMethodLike().prettyName() + + ", to=" + to.getMethodLike().prettyName() + + ", invokeOpCode=" + invokeOpCode + + ", isDeclared=" + isDeclared + + '}'; + } }