[Fb-contrib-commit] fb-contrib/src/com/mebigfatguy/fbcontrib/detect PossibleMemoryBloat.java,1.2,1.3
Brought to you by:
dbrosius
|
From: Dave B. <dbr...@us...> - 2006-03-08 04:38:35
|
Update of /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3019/src/com/mebigfatguy/fbcontrib/detect Modified Files: PossibleMemoryBloat.java Log Message: don't report static collections that have no 'increasing' methods eg. .add in methods other then constructors of static initializers. Also report the line number of this first increasing method. Index: PossibleMemoryBloat.java =================================================================== RCS file: /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/PossibleMemoryBloat.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- PossibleMemoryBloat.java 7 Mar 2006 06:28:33 -0000 1.2 +++ PossibleMemoryBloat.java 8 Mar 2006 04:38:31 -0000 1.3 @@ -1,11 +1,14 @@ package com.mebigfatguy.fbcontrib.detect; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import org.apache.bcel.classfile.Code; import org.apache.bcel.classfile.Field; import org.apache.bcel.classfile.JavaClass; +import org.apache.bcel.classfile.Method; import org.apache.bcel.generic.Type; import edu.umd.cs.findbugs.BugInstance; @@ -13,6 +16,7 @@ import edu.umd.cs.findbugs.BytecodeScanningDetector; import edu.umd.cs.findbugs.FieldAnnotation; import edu.umd.cs.findbugs.OpcodeStack; +import edu.umd.cs.findbugs.SourceLineAnnotation; import edu.umd.cs.findbugs.StatelessDetector; import edu.umd.cs.findbugs.ba.ClassContext; @@ -45,18 +49,35 @@ bloatableSigs.add("Ljava/util/TreeSet;"); bloatableSigs.add("Ljava/util/Vector;"); } - private static final Set<String> clearingMethods = new HashSet<String>(); + private static final Set<String> decreasingMethods = new HashSet<String>(); static { - clearingMethods.add("clear"); - clearingMethods.add("delete"); - clearingMethods.add("deleteCharAt"); - clearingMethods.add("pop"); - clearingMethods.add("remove"); - clearingMethods.add("setLength"); + decreasingMethods.add("clear"); + decreasingMethods.add("delete"); + decreasingMethods.add("deleteCharAt"); + decreasingMethods.add("pop"); + decreasingMethods.add("remove"); + decreasingMethods.add("removeAll"); + decreasingMethods.add("removeAllElements"); + decreasingMethods.add("removeElementAt"); + decreasingMethods.add("removeRange"); + decreasingMethods.add("setLength"); + } + + private static final Set<String> increasingMethods = new HashSet<String>(); + static { + increasingMethods.add("add"); + increasingMethods.add("addAll"); + increasingMethods.add("addElement"); + increasingMethods.add("addFirst"); + increasingMethods.add("addLast"); + increasingMethods.add("append"); + increasingMethods.add("insertElementAt"); + increasingMethods.add("put"); } private BugReporter bugReporter; - private Set<FieldAnnotation> bloatableFields = new HashSet<FieldAnnotation>(); + private Map<FieldAnnotation, SourceLineAnnotation> bloatableFields = new HashMap<FieldAnnotation, SourceLineAnnotation>(); private OpcodeStack stack = new OpcodeStack(); + private String methodName; /** * constructs a PMB detector given the reporter to report bugs on @@ -91,7 +112,7 @@ if (f.isStatic()) { String sig = f.getSignature(); if (bloatableSigs.contains(sig)) { - bloatableFields.add(FieldAnnotation.fromBCELField(cls.getClassName(), f)); + bloatableFields.put(FieldAnnotation.fromBCELField(cls.getClassName(), f), null); } } } @@ -99,15 +120,29 @@ if (bloatableFields.size() > 0) { super.visitClassContext(classContext); - for (FieldAnnotation fa : bloatableFields) { - bugReporter.reportBug(new BugInstance(this, "PMB_POSSIBLE_MEMORY_BLOAT", NORMAL_PRIORITY) - .addClass(this) - .addField(fa)); + for (Map.Entry<FieldAnnotation, SourceLineAnnotation> entry : bloatableFields.entrySet()) { + SourceLineAnnotation sla = entry.getValue(); + if (sla != null) { + bugReporter.reportBug(new BugInstance(this, "PMB_POSSIBLE_MEMORY_BLOAT", NORMAL_PRIORITY) + .addClass(this) + .addSourceLine(sla) + .addField(entry.getKey())); + } } } } /** + * implements the visitor to collect the method name + * + * @param obj the context object of the currently parsed method + */ + @Override + public void visitMethod(Method obj) { + methodName = obj.getName(); + } + + /** * implements the visitor to reset the opcode stack * * @param obj the context object of the currently parsed code block @@ -115,6 +150,11 @@ @Override public void visitCode(Code obj) { stack.resetForMethodEntry(this); + + if ("<clinit>".equals(methodName) + || "<init>".equals(methodName)) + return; + if (bloatableFields.size() > 0) super.visitCode(obj); } @@ -141,10 +181,15 @@ OpcodeStack.Item itm = stack.getStackItem(argCount); FieldAnnotation fa = itm.getField(); if (fa != null) { - if (bloatableFields.contains(fa)) { + if (bloatableFields.containsKey(fa)) { String methodName = getNameConstantOperand(); - if (clearingMethods.contains(methodName)) { + if (decreasingMethods.contains(methodName)) { bloatableFields.remove(fa); + } else if (increasingMethods.contains(methodName)) { + if (bloatableFields.get(fa) == null) { + SourceLineAnnotation sla = SourceLineAnnotation.fromVisitedInstruction(this); + bloatableFields.put(fa, sla); + } } } } |