KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > detect > LoadOfKnownNullValue


1 package edu.umd.cs.findbugs.detect;
2
3 import java.util.BitSet JavaDoc;
4 import java.util.IdentityHashMap JavaDoc;
5 import java.util.Iterator JavaDoc;
6
7 import org.apache.bcel.classfile.LineNumberTable;
8 import org.apache.bcel.classfile.Method;
9 import org.apache.bcel.generic.ALOAD;
10 import org.apache.bcel.generic.ARETURN;
11 import org.apache.bcel.generic.Instruction;
12 import org.apache.bcel.generic.InstructionHandle;
13 import org.apache.bcel.generic.MethodGen;
14
15 import edu.umd.cs.findbugs.BugInstance;
16 import edu.umd.cs.findbugs.BugReporter;
17 import edu.umd.cs.findbugs.Detector;
18 import edu.umd.cs.findbugs.SourceLineAnnotation;
19 import edu.umd.cs.findbugs.SystemProperties;
20 import edu.umd.cs.findbugs.ba.CFG;
21 import edu.umd.cs.findbugs.ba.CFGBuilderException;
22 import edu.umd.cs.findbugs.ba.ClassContext;
23 import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
24 import edu.umd.cs.findbugs.ba.Location;
25 import edu.umd.cs.findbugs.ba.MethodUnprofitableException;
26 import edu.umd.cs.findbugs.ba.npe.IsNullValue;
27 import edu.umd.cs.findbugs.ba.npe.IsNullValueDataflow;
28 import edu.umd.cs.findbugs.ba.npe.IsNullValueFrame;
29
30 public class LoadOfKnownNullValue implements Detector {
31
32     private BugReporter bugReporter;
33
34     public LoadOfKnownNullValue(BugReporter bugReporter) {
35         this.bugReporter = bugReporter;
36     }
37
38     public void visitClassContext(ClassContext classContext) {
39         Method[] methodList = classContext.getJavaClass().getMethods();
40
41         for (Method method : methodList) {
42             if (method.getCode() == null)
43                 continue;
44
45             try {
46                 analyzeMethod(classContext, method);
47             } catch (MethodUnprofitableException mue) {
48                 if (SystemProperties.getBoolean("unprofitable.debug")) // otherwise don't report
49
bugReporter.logError("skipping unprofitable method in " + getClass().getName());
50             } catch (CFGBuilderException e) {
51                 bugReporter.logError("Detector " + this.getClass().getName()
52                         + " caught exception", e);
53             } catch (DataflowAnalysisException e) {
54                 bugReporter.logError("Detector " + this.getClass().getName()
55                         + " caught exception", e);
56             }
57         }
58     }
59
60     private void analyzeMethod(ClassContext classContext, Method method)
61             throws CFGBuilderException, DataflowAnalysisException {
62         BitSet JavaDoc lineMentionedMultipleTimes = ClassContext.linesMentionedMultipleTimes(method);
63         BitSet JavaDoc linesWithLoadsOfNotDefinitelyNullValues = null;
64         
65         CFG cfg = classContext.getCFG(method);
66         IsNullValueDataflow nullValueDataflow = classContext
67                 .getIsNullValueDataflow(method);
68         MethodGen methodGen = classContext.getMethodGen(method);
69         String JavaDoc sourceFile = classContext.getJavaClass().getSourceFileName();
70
71         if (lineMentionedMultipleTimes.cardinality() > 0) {
72             linesWithLoadsOfNotDefinitelyNullValues = new BitSet JavaDoc();
73             LineNumberTable lineNumbers = method.getLineNumberTable();
74             for (Iterator JavaDoc<Location> i = cfg.locationIterator(); i.hasNext();) {
75                 Location location = i.next();
76
77                 InstructionHandle handle = location.getHandle();
78                 Instruction ins = handle.getInstruction();
79                 if (!(ins instanceof ALOAD))
80                     continue;
81
82                 IsNullValueFrame frame = nullValueDataflow
83                         .getFactAtLocation(location);
84                 if (!frame.isValid()) {
85                     // This basic block is probably dead
86
continue;
87                 }
88                 // System.out.println(handle.getPosition() + "\t" + ins.getName() + "\t" + frame);
89

90                 ALOAD load = (ALOAD) ins;
91
92                 int index = load.getIndex();
93                 IsNullValue v = frame.getValue(index);
94                 if (!v.isDefinitelyNull()) {
95                     int sourceLine = lineNumbers.getSourceLine(handle.getPosition());
96                     if (sourceLine > 0)
97                     linesWithLoadsOfNotDefinitelyNullValues.set(sourceLine);
98                 }
99         }
100         }
101         
102         
103         IdentityHashMap JavaDoc<InstructionHandle, Object JavaDoc> sometimesGood = new IdentityHashMap JavaDoc<InstructionHandle, Object JavaDoc>();
104         
105         for (Iterator JavaDoc<Location> i = cfg.locationIterator(); i.hasNext();) {
106             Location location = i.next();
107             InstructionHandle handle = location.getHandle();
108             Instruction ins = handle.getInstruction();
109             if (!(ins instanceof ALOAD)) continue;
110             IsNullValueFrame frame = nullValueDataflow.getFactAtLocation(location);
111             if (!frame.isValid()) {
112                 // This basic block is probably dead
113
continue;
114             }
115             // System.out.println(handle.getPosition() + "\t" + ins.getName() + "\t" + frame);
116

117             ALOAD load = (ALOAD) ins;
118
119             int index = load.getIndex();
120             IsNullValue v = frame.getValue(index);
121             if (!v.isDefinitelyNull()) sometimesGood.put(handle, null);
122         }
123         
124         // System.out.println(nullValueDataflow);
125
for (Iterator JavaDoc<Location> i = cfg.locationIterator(); i.hasNext();) {
126             Location location = i.next();
127
128             InstructionHandle handle = location.getHandle();
129             Instruction ins = handle.getInstruction();
130             if (!(ins instanceof ALOAD))
131                 continue;
132
133             if (sometimesGood.containsKey(handle)) continue;
134             IsNullValueFrame frame = nullValueDataflow
135                     .getFactAtLocation(location);
136             if (!frame.isValid()) {
137                 // This basic block is probably dead
138
continue;
139             }
140             // System.out.println(handle.getPosition() + "\t" + ins.getName() + "\t" + frame);
141

142             ALOAD load = (ALOAD) ins;
143
144             int index = load.getIndex();
145             IsNullValue v = frame.getValue(index);
146             if (v.isDefinitelyNull()) {
147                 Instruction next = handle.getNext().getInstruction();
148                 InstructionHandle prevHandle = handle.getPrev();
149                 SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation
150                 .fromVisitedInstruction(classContext, methodGen, sourceFile, handle);
151                 SourceLineAnnotation prevSourceLineAnnotation = SourceLineAnnotation
152                 .fromVisitedInstruction(classContext, methodGen, sourceFile, prevHandle);
153     
154                 if (next instanceof ARETURN) {
155                     // probably stored for duration of finally block
156
continue;
157                 }
158                 int startLine = sourceLineAnnotation.getStartLine();
159                 if (startLine > 0 && lineMentionedMultipleTimes.get(startLine) && linesWithLoadsOfNotDefinitelyNullValues.get(startLine))
160                     continue;
161                 
162                 if (startLine > prevSourceLineAnnotation.getEndLine()) {
163                     // probably stored for duration of finally block
164
// System.out.println("Inverted line");
165
continue;
166                 }
167                 int priority = NORMAL_PRIORITY;
168                 
169                 if (!v.isChecked()) priority++;
170                 // System.out.println("lineMentionedMultipleTimes: " + lineMentionedMultipleTimes);
171
// System.out.println("linesWithLoadsOfNonNullValues: " + linesWithLoadsOfNotDefinitelyNullValues);
172

173                 bugReporter.reportBug(new BugInstance(this,
174                         "NP_LOAD_OF_KNOWN_NULL_VALUE",
175                         priority)
176                         .addClassAndMethod(methodGen, sourceFile)
177                         .addSourceLine(sourceLineAnnotation));
178             }
179
180         }
181     }
182
183     public void report() {
184     }
185
186 }
187
Popular Tags