KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2003,2004 University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 package edu.umd.cs.findbugs.detect;
21
22
23 import edu.umd.cs.findbugs.*;
24 import java.util.*;
25 import org.apache.bcel.Repository;
26 import org.apache.bcel.classfile.*;
27
28 public class FindDoubleCheck extends BytecodeScanningDetector {
29     static final boolean DEBUG = false;
30     int stage = 0;
31     int startPC, endPC;
32     int count;
33     boolean sawMonitorEnter;
34     Set<FieldAnnotation> fields = new HashSet<FieldAnnotation>();
35     Set<FieldAnnotation> twice = new HashSet<FieldAnnotation>();
36     FieldAnnotation pendingFieldLoad;
37
38     int countSinceGetReference;
39     int countSinceGetBoolean;
40     private BugReporter bugReporter;
41
42     public FindDoubleCheck(BugReporter bugReporter) {
43         this.bugReporter = bugReporter;
44     }
45
46     @Override JavaDoc
47          public void visit(Method obj) {
48         if (DEBUG) System.out.println(getFullyQualifiedMethodName());
49         super.visit(obj);
50         fields.clear();
51         twice.clear();
52         stage = 0;
53         count = 0;
54         countSinceGetReference = 1000;
55         countSinceGetBoolean = 1000;
56         sawMonitorEnter = false;
57         pendingFieldLoad = null;
58     }
59
60     @Override JavaDoc
61          public void sawOpcode(int seen) {
62         if (DEBUG) System.out.println(getPC() + " " + OPCODE_NAMES[seen] + " " + stage + " " + count + " " + countSinceGetReference);
63
64         if (seen == MONITORENTER) sawMonitorEnter = true;
65         if (seen == GETFIELD || seen == GETSTATIC) {
66             pendingFieldLoad = FieldAnnotation.fromReferencedField(this);
67             if (DEBUG) System.out.println(" " + pendingFieldLoad);
68             String JavaDoc sig = getSigConstantOperand();
69             if (sig.equals("Z")) {
70                 countSinceGetBoolean = 0;
71                 countSinceGetReference++;
72             } else if (sig.startsWith("L") || sig.startsWith("[")) {
73                 countSinceGetBoolean++;
74                 countSinceGetReference = 0;
75             }
76         } else {
77             countSinceGetReference++;
78         }
79         switch (stage) {
80         case 0:
81             if (((seen == IFNULL || seen == IFNONNULL) && countSinceGetReference < 5)
82                     || ((seen == IFEQ || seen == IFNE) && countSinceGetBoolean < 5)) {
83                 int b = getBranchOffset();
84                 if (DEBUG) {
85                     System.out.println("branch offset is : " + b);
86                 }
87                 if (b > 0
88                         && !(seen == IFNULL && b > 9)
89                         && !(seen == IFEQ && (b > 9 && b < 34))
90                         && !(seen == IFNE && (b > 9 && b < 34))
91                         && (!sawMonitorEnter)) {
92                     fields.add(pendingFieldLoad);
93                     startPC = getPC();
94                     stage = 1;
95                 }
96             }
97             count = 0;
98             break;
99         case 1:
100             if (seen == MONITORENTER) {
101                 stage = 2;
102                 count = 0;
103             } else if (((seen == IFNULL || seen == IFNONNULL) && countSinceGetReference < 5)
104                     || ((seen == IFEQ || seen == IFNE) && countSinceGetBoolean < 5)) {
105                 int b = getBranchOffset();
106                 if (b > 0 && (seen == IFNONNULL || b < 10)) {
107                     fields.add(pendingFieldLoad);
108                     startPC = getPC();
109                     count = 0;
110                 }
111             } else {
112                 count++;
113                 if (count > 10) stage = 0;
114             }
115             break;
116         case 2:
117             if (((seen == IFNULL || seen == IFNONNULL) && countSinceGetReference < 5)
118                     || ((seen == IFEQ || seen == IFNE) && countSinceGetBoolean < 5)) {
119                 if (getBranchOffset() >= 0 && fields.contains(pendingFieldLoad)) {
120                     endPC = getPC();
121                     stage++;
122                     twice.add(pendingFieldLoad);
123                     break;
124                 }
125             }
126             count++;
127             if (count > 10) stage = 0;
128             break;
129         case 3:
130             if (seen == PUTFIELD || seen == PUTSTATIC) {
131                 FieldAnnotation f = FieldAnnotation.fromReferencedField(this);
132                 if (DEBUG) System.out.println(" " + f);
133                 if (twice.contains(f) && !getNameConstantOperand().startsWith("class$")
134                         && !getSigConstantOperand().equals("Ljava/lang/String;")) {
135                     Field declaration = findField(getClassConstantOperand(), getNameConstantOperand());
136                     /*
137                     System.out.println(f);
138                     System.out.println(declaration);
139                     System.out.println(getSigConstantOperand());
140                     */

141                     if (declaration == null || !declaration.isVolatile())
142                         bugReporter.reportBug(new BugInstance(this, "DC_DOUBLECHECK", NORMAL_PRIORITY)
143                                 .addClassAndMethod(this)
144                                 .addField(f).describe("FIELD_ON")
145                                 .addSourceLineRange(this, startPC, endPC));
146                     stage++;
147                 }
148             }
149             break;
150         default:
151         }
152     }
153
154     Field findField(String JavaDoc className, String JavaDoc fieldName) {
155         try {
156             // System.out.println("Looking for " + className);
157
JavaClass fieldDefinedIn = getThisClass();
158             if (!className.equals(getClassName())) {
159                 // System.out.println("Using repository to look for " + className);
160

161                 fieldDefinedIn = Repository.lookupClass(className);
162             }
163             Field[] f = fieldDefinedIn.getFields();
164             for (Field aF : f)
165                 if (aF.getName().equals(fieldName)) {
166                     // System.out.println("Found " + f[i]);
167
return aF;
168                 }
169             return null;
170         } catch (ClassNotFoundException JavaDoc e) {
171             return null;
172         }
173     }
174
175 }
176
Popular Tags