1 19 20 package edu.umd.cs.findbugs.detect; 21 22 23 import edu.umd.cs.findbugs.*; 24 import edu.umd.cs.findbugs.ba.ClassContext; 25 import java.util.*; 26 import org.apache.bcel.classfile.Field; 27 28 public class VolatileUsage extends BytecodeScanningDetector { 29 private BugReporter bugReporter; 30 31 public VolatileUsage(BugReporter bugReporter) { 32 this.bugReporter = bugReporter; 33 } 34 35 @Override 36 public void visitClassContext(ClassContext classContext) { 37 classContext.getJavaClass().accept(this); 38 } 39 40 static class FieldRecord { 41 String className; 42 String name; 43 String signature; 44 boolean isStatic; 45 } 46 47 48 Map<String ,FieldRecord> fieldInfo = new HashMap<String ,FieldRecord>(); 49 Set<String > initializationWrites = new HashSet<String >(); 50 Set<String > otherWrites = new HashSet<String >(); 51 52 53 @Override 54 public void visit(Field obj) { 55 super.visit(obj); 56 int flags = obj.getAccessFlags(); 57 if ((flags & ACC_VOLATILE) == 0) return; 58 if (getFieldSig().charAt(0) == '[') { 59 FieldRecord f = new FieldRecord(); 60 f.className = getDottedClassName(); 61 f.name = getFieldName(); 62 f.signature = getFieldSig(); 63 f.isStatic = !((flags & ACC_STATIC) == 0); 64 fieldInfo.put(getDottedClassName() + "." + getFieldName(), 65 f); 66 } 67 } 68 69 @Override 70 public void sawOpcode(int seen) { 71 switch (seen) { 72 case PUTSTATIC: 73 { 74 String name = (getClassConstantOperand() 75 + "." + getNameConstantOperand()) 76 .replace('/', '.'); 77 if (getMethodName().equals("<clinit>")) 78 initializationWrites.add(name); 79 else otherWrites.add(name); 80 break; 81 } 82 case PUTFIELD: 83 { 84 String name = (getClassConstantOperand() 85 + "." + getNameConstantOperand()) 86 .replace('/', '.'); 87 if (getMethodName().equals("<init>")) 88 initializationWrites.add(name); 89 else otherWrites.add(name); 90 break; 91 } 92 } 93 } 94 95 96 @Override 97 public void report() { 98 99 for(Map.Entry<String , FieldRecord> r : fieldInfo.entrySet()) { 100 String name = r.getKey(); 101 FieldRecord f = r.getValue(); 102 int priority = LOW_PRIORITY; 103 if (initializationWrites.contains(name) 104 && !otherWrites.contains(name)) 105 priority = NORMAL_PRIORITY; 106 bugReporter.reportBug( 107 new BugInstance(this, "VO_VOLATILE_REFERENCE_TO_ARRAY", priority) 108 .addClass(f.className) 109 .addField(f.className, f.name, f.signature, f.isStatic)); 110 } 111 } 112 } 113 | Popular Tags |