1 19 20 package edu.umd.cs.findbugs; 21 22 import java.util.HashSet ; 23 import java.util.Iterator ; 24 25 import org.apache.bcel.classfile.JavaClass; 26 import org.apache.bcel.classfile.Method; 27 import org.apache.bcel.generic.ConstantPoolGen; 28 import org.apache.bcel.generic.INVOKESTATIC; 29 import org.apache.bcel.generic.Instruction; 30 import org.apache.bcel.generic.InstructionHandle; 31 import org.apache.bcel.generic.InvokeInstruction; 32 import org.apache.bcel.generic.MONITORENTER; 33 import org.apache.bcel.generic.MONITOREXIT; 34 import org.apache.bcel.generic.MethodGen; 35 36 import edu.umd.cs.findbugs.ba.BasicBlock; 37 import edu.umd.cs.findbugs.ba.CFG; 38 import edu.umd.cs.findbugs.ba.CFGBuilderException; 39 import edu.umd.cs.findbugs.ba.ClassContext; 40 41 44 public class SelfCalls { 45 private static final boolean DEBUG = SystemProperties.getBoolean("selfcalls.debug"); 46 47 private ClassContext classContext; 48 private CallGraph callGraph; 49 private HashSet <Method> calledMethodSet; 50 private boolean hasSynchronization; 51 52 57 public SelfCalls(ClassContext classContext) { 58 this.classContext = classContext; 59 this.callGraph = new CallGraph(); 60 this.calledMethodSet = new HashSet <Method>(); 61 this.hasSynchronization = false; 62 } 63 64 67 public void execute() throws CFGBuilderException { 68 JavaClass jclass = classContext.getJavaClass(); 69 Method[] methods = jclass.getMethods(); 70 71 if (DEBUG) System.out.println("Class has " + methods.length + " methods"); 72 73 for (Method method : methods) { 75 callGraph.addNode(method); 76 } 77 if (DEBUG) System.out.println("Added " + callGraph.getNumVertices() + " nodes to graph"); 78 79 for (Method method : methods) { 81 MethodGen mg = classContext.getMethodGen(method); 82 if (mg == null) 83 continue; 84 85 scan(callGraph.getNodeForMethod(method)); 86 } 87 88 if (DEBUG) System.out.println("Found " + callGraph.getNumEdges() + " self calls"); 89 } 90 91 94 public CallGraph getCallGraph() { 95 return callGraph; 96 } 97 98 101 public Iterator <Method> calledMethodIterator() { 102 return calledMethodSet.iterator(); 103 } 104 105 113 public boolean wantCallsFor(Method method) { 114 return true; 115 } 116 117 120 public Iterator <CallSite> callSiteIterator() { 121 return new Iterator <CallSite>() { 122 private Iterator <CallGraphEdge> iter = callGraph.edgeIterator(); 123 124 public boolean hasNext() { 125 return iter.hasNext(); 126 } 127 128 public CallSite next() { 129 return iter.next().getCallSite(); 130 } 131 132 public void remove() { 133 iter.remove(); 134 } 135 }; 136 } 137 138 141 public boolean hasSynchronization() { 142 return hasSynchronization; 143 } 144 145 150 private void scan(CallGraphNode node) throws CFGBuilderException { 151 Method method = node.getMethod(); 152 CFG cfg = classContext.getCFG(method); 153 154 if (method.isSynchronized()) 155 hasSynchronization = true; 156 157 Iterator <BasicBlock> i = cfg.blockIterator(); 158 while (i.hasNext()) { 159 BasicBlock block = i.next(); 160 Iterator <InstructionHandle> j = block.instructionIterator(); 161 while (j.hasNext()) { 162 InstructionHandle handle = j.next(); 163 164 Instruction ins = handle.getInstruction(); 165 if (ins instanceof InvokeInstruction) { 166 InvokeInstruction inv = (InvokeInstruction) ins; 167 Method called = isSelfCall(inv); 168 if (called != null) { 169 CallSite callSite = new CallSite(method, block, handle); 171 callGraph.createEdge(node, callGraph.getNodeForMethod(called), callSite); 172 173 calledMethodSet.add(called); 175 } 176 } else if (ins instanceof MONITORENTER || ins instanceof MONITOREXIT) { 177 hasSynchronization = true; 178 } 179 } 180 } 181 } 182 183 186 private Method isSelfCall(InvokeInstruction inv) { 187 ConstantPoolGen cpg = classContext.getConstantPoolGen(); 188 JavaClass jclass = classContext.getJavaClass(); 189 190 String calledClassName = inv.getClassName(cpg); 191 192 if (!calledClassName.equals(jclass.getClassName())) 197 return null; 198 199 String calledMethodName = inv.getMethodName(cpg); 200 String calledMethodSignature = inv.getSignature(cpg); 201 boolean isStaticCall = (inv instanceof INVOKESTATIC); 202 203 Method[] methods = jclass.getMethods(); 205 for (Method method : methods) { 206 String methodName = method.getName(); 207 String signature = method.getSignature(); 208 boolean isStatic = method.isStatic(); 209 210 if (methodName.equals(calledMethodName) && 211 signature.equals(calledMethodSignature) && 212 isStatic == isStaticCall) { 213 return wantCallsFor(method) ? method : null; 215 } 216 } 217 218 if (DEBUG) System.out.println("No method found for " + calledClassName + "." + calledMethodName + " : " + calledMethodSignature); 222 return null; 223 } 224 } 225 226 | Popular Tags |