1 19 20 package edu.umd.cs.findbugs.detect; 21 22 23 import edu.umd.cs.findbugs.*; 24 import edu.umd.cs.findbugs.ba.*; 25 import java.util.*; 26 import org.apache.bcel.classfile.*; 27 import org.apache.bcel.generic.*; 28 29 public final class FindTwoLockWait implements Detector, StatelessDetector { 30 31 private BugReporter bugReporter; 32 private JavaClass javaClass; 33 34 private Collection<BugInstance> possibleWaitBugs = new LinkedList<BugInstance>(); 35 private Collection<SourceLineAnnotation> possibleNotifyLocations = new LinkedList<SourceLineAnnotation>(); 36 public FindTwoLockWait(BugReporter bugReporter) { 37 this.bugReporter = bugReporter; 38 } 39 40 @Override 41 public Object clone() { 42 try { 43 return super.clone(); 44 } catch (CloneNotSupportedException e) { 45 throw new AssertionError (e); 46 } 47 } 48 49 public void visitClassContext(ClassContext classContext) { 50 javaClass = classContext.getJavaClass(); 51 possibleWaitBugs.clear(); 52 possibleNotifyLocations.clear(); 53 Method[] methodList = javaClass.getMethods(); 54 for (Method method : methodList) { 55 MethodGen methodGen = classContext.getMethodGen(method); 56 if (methodGen == null) 57 continue; 58 59 if (!preScreen(methodGen)) 60 continue; 61 62 try { 63 analyzeMethod(classContext, method); 64 } catch (DataflowAnalysisException e) { 65 } catch (CFGBuilderException e) { 67 bugReporter.logError("Error analyzing " + method.toString(), e); 68 } 69 } 70 if (!possibleNotifyLocations.isEmpty()) 71 for(BugInstance bug : possibleWaitBugs ) { 72 for(SourceLineAnnotation notifyLine : possibleNotifyLocations) 73 bug.addSourceLine(notifyLine).describe("SOURCE_NOTIFICATION_DEADLOCK"); 74 bugReporter.reportBug(bug); 75 } 76 } 77 78 private void analyzeMethod(ClassContext classContext, Method method) 79 throws CFGBuilderException, DataflowAnalysisException { 80 81 MethodGen methodGen = classContext.getMethodGen(method); 82 CFG cfg = classContext.getCFG(method); 83 LockDataflow dataflow = classContext.getLockDataflow(method); 84 85 for (Iterator<Location> j = cfg.locationIterator(); j.hasNext();) { 86 Location location = j.next(); 87 visitLocation(classContext, location, methodGen, dataflow); 88 } 89 } 90 91 public boolean preScreen(MethodGen mg) { 92 ConstantPoolGen cpg = mg.getConstantPool(); 93 94 int lockCount = mg.isSynchronized() ? 1 : 0; 95 boolean sawWaitOrNotify = false; 96 97 InstructionHandle handle = mg.getInstructionList().getStart(); 98 while (handle != null && !(lockCount >= 2 && sawWaitOrNotify)) { 99 Instruction ins = handle.getInstruction(); 100 if (ins instanceof MONITORENTER) 101 ++lockCount; 102 else if (ins instanceof INVOKEVIRTUAL) { 103 INVOKEVIRTUAL inv = (INVOKEVIRTUAL) ins; 104 String methodName = inv.getMethodName(cpg); 105 if (methodName.equals("wait") || methodName.startsWith("notify")) 106 sawWaitOrNotify = true; 107 } 108 109 handle = handle.getNext(); 110 } 111 112 return lockCount >= 2 && sawWaitOrNotify; 113 } 114 115 public void visitLocation(ClassContext classContext, Location location, MethodGen methodGen, LockDataflow dataflow) throws DataflowAnalysisException { 116 ConstantPoolGen cpg = methodGen.getConstantPool(); 117 118 if (Hierarchy.isMonitorWait(location.getHandle().getInstruction(), cpg)) { 119 int count = dataflow.getFactAtLocation(location).getNumLockedObjects(); 120 if (count > 1) { 121 String sourceFile = javaClass.getSourceFileName(); 123 possibleWaitBugs.add(new BugInstance(this, "TLW_TWO_LOCK_WAIT", HIGH_PRIORITY ) 124 .addClass(javaClass) 125 .addMethod(methodGen, sourceFile) 126 .addSourceLine(classContext, methodGen, sourceFile, location.getHandle())); 127 } 128 } 129 if (Hierarchy.isMonitorNotify(location.getHandle().getInstruction(), cpg)) { 130 int count = dataflow.getFactAtLocation(location).getNumLockedObjects(); 131 if (count > 1) { 132 String sourceFile = javaClass.getSourceFileName(); 134 possibleNotifyLocations.add(SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile, location.getHandle())); 135 } 136 } 137 } 138 139 public void report() { 140 } 141 } 142 143 | Popular Tags |