Update of /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19962/src/com/mebigfatguy/fbcontrib/detect
Added Files:
BloatedSynchronizedBlock.java
Log Message:
initial checkin - BSB -- not working yet, so hidden
--- NEW FILE: BloatedSynchronizedBlock.java ---
/*
* fb-contrib - Auxilliary detectors for Java programs
* Copyright (C) 2005 Dave Brosius
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.mebigfatguy.fbcontrib.detect;
import org.apache.bcel.Constants;
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;
public class BloatedSynchronizedBlock extends BytecodeScanningDetector implements StatelessDetector
{
private BugReporter bugReporter;
private static final String BSB_MIN_SAFE_CODE_SIZE = "fb-contrib.bsb.minsize";
private OpcodeStack stack = new OpcodeStack();
private int syncPC;
private int lastPC;
private int startSafe;
private boolean isStatic;
private int minSafeCodeLength;
/**
* constructs a BSB detector given the reporter to report bugs on
* @param bugReporter the sync of bug reports
*/
public BloatedSynchronizedBlock(BugReporter bugReporter) {
this.bugReporter = bugReporter;
minSafeCodeLength = Integer.getInteger(BSB_MIN_SAFE_CODE_SIZE, 10);
}
/**
* clone this detector so that it can be a StatelessDetector
*
* @return a clone of this object
*/
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
/**
* implement the visitor to reset the sync count, the stack, and gather some information
*
* @param obj the context object for the currently parsed method
*/
@Override
public void visitMethod(Method obj) {
if (obj.isSynchronized())
syncPC = 0;
else
syncPC = -1;
stack.resetForMethodEntry(this);
startSafe = 0;
lastPC = -1;
isStatic = obj.isStatic();
}
/**
* implement the visitor to find bloated sync blocks. This implementation
* only checks the outer most block
*
* @param seen the opcode of the currently parsed instruction
*/
public void sawOpcode(int seen) {
try {
if ("BSB_Sample".equals(getClassName()))
System.out.println(Constants.OPCODE_NAMES[seen]);
if (seen == MONITORENTER) {
if (syncPC < 0) {
syncPC = getPC();
startSafe = this.getNextPC();
}
}
else if (seen == MONITOREXIT) {
if ((startSafe >= 0) && ((getPC() - startSafe) > minSafeCodeLength)) {
bugReporter.reportBug(new BugInstance(this, "BSB_BLOATED_SYNCHRONIZED_BLOCK", NORMAL_PRIORITY)
.addClass(this)
.addMethod(this)
.addSourceLineRange(this, startSafe, lastPC));
}
syncPC = -1;
startSafe = -1;
}
else {
boolean unsafe = ((seen == PUTFIELD) || (seen == GETFIELD));
unsafe |= (!isStatic) && ((seen == ALOAD_0) || (seen == ASTORE_0));
if (unsafe) {
if (syncPC >= 0) {
if ((getPC() - startSafe) > minSafeCodeLength) {
bugReporter.reportBug(new BugInstance(this, "BSB_BLOATED_SYNCHRONIZED_BLOCK", NORMAL_PRIORITY)
.addClass(this)
.addMethod(this)
.addSourceLineRange(this, startSafe, lastPC));
}
}
startSafe = -1;
syncPC = -1;
} else if (startSafe < 0) {
int depth = stack.getStackDepth();
int i;
for (i = 0; i < depth; i++) {
OpcodeStack.Item item = stack.getStackItem(i);
if (item.getField() != null) {
break;
}
}
if (i == depth)
startSafe = getPC();
}
}
lastPC = getPC();
} finally {
stack.sawOpcode(this, seen);
}
}
}
|