[Fb-contrib-commit] fb-contrib/src/com/mebigfatguy/fbcontrib/detect SuspiciousWaitOnConcurrentObject
Brought to you by:
dbrosius
|
From: Dave B. <dbr...@us...> - 2006-03-05 04:37:20
|
Update of /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7897/src/com/mebigfatguy/fbcontrib/detect Added Files: SuspiciousWaitOnConcurrentObject.java Log Message: initial checkin - new SWCO detector --- NEW FILE: SuspiciousWaitOnConcurrentObject.java --- package com.mebigfatguy.fbcontrib.detect; import java.util.HashSet; import java.util.Set; import org.apache.bcel.Constants; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.Method; import edu.umd.cs.findbugs.BugInstance; import edu.umd.cs.findbugs.BugReporter; import edu.umd.cs.findbugs.BytecodeScanningDetector; import edu.umd.cs.findbugs.OpcodeStack; import edu.umd.cs.findbugs.StatelessDetector; import edu.umd.cs.findbugs.ba.ClassContext; /** * looks for calls to the wait method on mutexes defined in the java.util.concurrent package * where it is likely that await was intended. */ public class SuspiciousWaitOnConcurrentObject extends BytecodeScanningDetector implements StatelessDetector { private static final Set<String> concurrentAwaitClasses = new HashSet<String>(); static { concurrentAwaitClasses.add("java.util.concurrent.CountDownLatch"); concurrentAwaitClasses.add("java.util.concurrent.CyclicBarrier"); } private BugReporter bugReporter; private OpcodeStack stack = new OpcodeStack(); /** * constructs a SWCO detector given the reporter to report bugs on * @param bugReporter the sync of bug reports */ public SuspiciousWaitOnConcurrentObject(BugReporter bugReporter) { this.bugReporter = bugReporter; } /** * clone this detector so that it can be a StatelessDetector * * @return a clone of this object */ @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } /** * implements the visitor to check for class file version 1.5 or better * * @param classContext the context object of the currently parsed class */ @Override public void visitClassContext(ClassContext classContext) { JavaClass cls = classContext.getJavaClass(); int major = cls.getMajor(); if (major >= Constants.MAJOR_1_5) { super.visitClassContext(classContext); } } /** * implements the visitor to reset the opcode stack * * @param obj the context object for the currently parsed method */ @Override public void visitMethod(Method obj) { stack.resetForMethodEntry(this); } /** * implements the visitor to look for calls to wait, on java.util.concurrent * classes that define await. * * @param seen the opcode of the currently visited instruction */ @Override public void sawOpcode(int seen) { try { stack.mergeJumps(this); if (seen == INVOKEVIRTUAL) { String methodName = getNameConstantOperand(); if ("wait".equals(methodName)) { if (stack.getStackDepth() > 0) { OpcodeStack.Item itm = stack.getStackItem(0); JavaClass cls = itm.getJavaClass(); String clsName = cls.getClassName(); if (concurrentAwaitClasses.contains(clsName)) { bugReporter.reportBug(new BugInstance(this, "SWCO_SUSPICIOUS_WAIT_ON_CONCURRENT_OBJECT", NORMAL_PRIORITY) .addClass(this) .addMethod(this) .addSourceLine(this)); } } } } } catch (ClassNotFoundException cnfe) { bugReporter.reportMissingClass(cnfe); } finally { stack.sawOpcode(this, seen); } } } |