1 19 20 package edu.umd.cs.findbugs.detect; 21 22 import java.util.HashMap ; 23 import java.util.HashSet ; 24 import java.util.Set ; 25 import java.util.Map ; 26 27 import edu.umd.cs.findbugs.*; 28 import edu.umd.cs.findbugs.ba.XFactory; 29 import edu.umd.cs.findbugs.ba.XField; 30 31 import org.apache.bcel.classfile.*; 32 import org.jaxen.function.StringLengthFunction; 33 34 public class HugeSharedStringConstants extends BytecodeScanningDetector { 35 36 39 private static final int SIZE_OF_HUGE_CONSTANT = 500; 40 41 String getStringKey(String s) { 42 return s.length() + ":" + s.hashCode(); 43 } 44 45 HashMap <String , Set <String >> map = new HashMap <String , Set <String >>(); 46 47 HashMap <String , XField> definition = new HashMap <String , XField>(); 48 49 HashMap <String , Integer > stringSize = new HashMap <String , Integer >(); 50 51 BugReporter bugReporter; 52 53 public HugeSharedStringConstants(BugReporter bugReporter) { 54 this.bugReporter = bugReporter; 55 } 56 57 @Override 58 public void visit(ConstantString s) { 59 String value = s.getBytes(getConstantPool()); 60 if (value.length() < SIZE_OF_HUGE_CONSTANT) 61 return; 62 String key = getStringKey(value); 63 Set <String > set = map.get(key); 64 if (set == null) { 65 set = new HashSet <String >(); 66 map.put(key, set); 67 } 68 set.add(getDottedClassName()); 69 } 70 71 @Override 72 public void visit(ConstantValue s) { 73 if (!visitingField()) 74 return; 75 int i = s.getConstantValueIndex(); 76 Constant c = getConstantPool().getConstant(i); 77 if (c instanceof ConstantString) { 78 String value = ((ConstantString) c).getBytes(getConstantPool()); 79 if (value.length() < SIZE_OF_HUGE_CONSTANT) 80 return; 81 String key = getStringKey(value); 82 definition.put(key, XFactory.createXField(this)); 83 stringSize.put(key, value.length()); 84 } 85 86 } 87 88 @Override 89 public void report() { 90 for (Map.Entry <String , Set <String >> e : map.entrySet()) { 91 Set <String > occursIn = e.getValue(); 92 if (occursIn.size() == 1) 93 continue; 94 XField field = definition.get(e.getKey()); 95 if (field == null) continue; 96 Integer length = stringSize.get(e.getKey()); 97 int overhead = length * (occursIn.size()-1); 98 if (overhead < 3*SIZE_OF_HUGE_CONSTANT) continue; 99 String className = field.getClassName(); 100 101 BugInstance bug = new BugInstance(this, "HSC_HUGE_SHARED_STRING_CONSTANT", 102 overhead > 20*SIZE_OF_HUGE_CONSTANT ? HIGH_PRIORITY : 103 ( overhead > 8*SIPUSH ? NORMAL_PRIORITY : LOW_PRIORITY)) 104 .addClass(className).addField(field).addInt(length).addInt(occursIn.size()-1); 105 for (String c : occursIn) 106 if (!c.equals(className)) 107 bug.addClass(c); 108 109 bugReporter.reportBug(bug); 110 111 } 112 113 } 114 115 } 116 | Popular Tags |