1 19 package edu.umd.cs.findbugs.detect; 20 21 import java.util.BitSet ; 22 import java.util.Iterator ; 23 24 import org.apache.bcel.Constants; 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.MethodGen; 31 32 import edu.umd.cs.findbugs.BugInstance; 33 import edu.umd.cs.findbugs.BugReporter; 34 import edu.umd.cs.findbugs.Detector; 35 import edu.umd.cs.findbugs.ba.CFG; 36 import edu.umd.cs.findbugs.ba.CFGBuilderException; 37 import edu.umd.cs.findbugs.ba.ClassContext; 38 import edu.umd.cs.findbugs.ba.DataflowAnalysisException; 39 import edu.umd.cs.findbugs.ba.Location; 40 import edu.umd.cs.findbugs.ba.LockDataflow; 41 import edu.umd.cs.findbugs.ba.LockSet; 42 43 48 public class FindSleepWithLockHeld implements Detector { 49 50 private BugReporter bugReporter; 51 52 public FindSleepWithLockHeld(BugReporter bugReporter) { 53 this.bugReporter = bugReporter; 54 } 55 56 public void visitClassContext(ClassContext classContext) { 57 JavaClass javaClass = classContext.getJavaClass(); 58 59 Method[] methodList = javaClass.getMethods(); 60 for (Method method : methodList) { 61 if (method.getCode() == null) 62 continue; 63 64 if (!prescreen(classContext, method)) 65 continue; 66 67 try { 68 analyzeMethod(classContext, method); 69 } catch (CFGBuilderException e) { 70 bugReporter.logError("FindSleepWithLockHeld caught exception", e); 71 } catch (DataflowAnalysisException e) { 72 bugReporter.logError("FindSleepWithLockHeld caught exception", e); 73 } 74 } 75 } 76 77 private boolean prescreen(ClassContext classContext, Method method) { 78 BitSet bytecodeSet = classContext.getBytecodeSet(method); 79 if (bytecodeSet == null) return false; 80 if (!bytecodeSet.get(Constants.MONITORENTER) && !method.isSynchronized()) 82 return false; 83 84 if (!bytecodeSet.get(Constants.INVOKESTATIC)) 86 return false; 87 88 return true; 89 } 90 91 private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException { 92 94 CFG cfg = classContext.getCFG(method); 95 LockDataflow lockDataflow = classContext.getLockDataflow(method); 96 97 for (Iterator <Location> i = cfg.locationIterator(); i.hasNext();) { 98 Location location = i.next(); 99 Instruction ins = location.getHandle().getInstruction(); 100 101 if (!(ins instanceof INVOKESTATIC)) 102 continue; 103 104 if (!isSleep((INVOKESTATIC) ins, classContext.getConstantPoolGen())) 105 continue; 106 107 109 LockSet lockSet = lockDataflow.getFactAtLocation(location); 110 if (lockSet.getNumLockedObjects() > 0) { 111 MethodGen mg = classContext.getMethodGen(method); 112 String sourceFile = classContext.getJavaClass().getSourceFileName(); 113 bugReporter.reportBug(new BugInstance("SWL_SLEEP_WITH_LOCK_HELD", NORMAL_PRIORITY) 114 .addClassAndMethod(mg, sourceFile) 115 .addSourceLine(classContext, mg, sourceFile, location.getHandle())); 116 } 117 } 118 } 119 120 private boolean isSleep(INVOKESTATIC ins, ConstantPoolGen cpg) { 121 String className = ins.getClassName(cpg); 122 if (!className.equals("java.lang.Thread")) 123 return false; 124 String methodName = ins.getMethodName(cpg); 125 String signature = ins.getSignature(cpg); 126 127 return methodName.equals("sleep") 128 && (signature.equals("(J)V") || signature.equals("(JI)V")); 129 } 130 131 public void report() { 132 } 133 134 } 135 | Popular Tags |