KickJava   Java API By Example, From Geeks To Geeks.

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


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
25 import java.util.*;
26 import org.apache.bcel.classfile.Code;
27
28 public class InitializationChain extends BytecodeScanningDetector {
29     Set<String JavaDoc> requires = new TreeSet<String JavaDoc>();
30     Map<String JavaDoc, Set<String JavaDoc>> classRequires = new TreeMap<String JavaDoc, Set<String JavaDoc>>();
31     private BugReporter bugReporter;
32     private boolean instanceCreated;
33     private int instanceCreatedPC;
34     private boolean instanceCreatedWarningGiven;
35
36     private static final boolean DEBUG = SystemProperties.getBoolean("ic.debug");
37     private static final boolean REPORT_CREATE_INSTANCE_BEFORE_FIELDS_ASSIGNED =
38             SystemProperties.getBoolean("ic.createInstance");
39
40     public InitializationChain(BugReporter bugReporter) {
41         this.bugReporter = bugReporter;
42     }
43
44     @Override JavaDoc
45          public void visit(Code obj) {
46         instanceCreated = false;
47         instanceCreatedWarningGiven = false;
48         if (!getMethodName().equals("<clinit>")) return;
49         super.visit(obj);
50         requires.remove(getDottedClassName());
51         if (getDottedClassName().equals("java.lang.System")) {
52             requires.add("java.io.FileInputStream");
53             requires.add("java.io.FileOutputStream");
54             requires.add("java.io.BufferedInputStream");
55             requires.add("java.io.BufferedOutputStream");
56             requires.add("java.io.PrintStream");
57         }
58         if (!requires.isEmpty()) {
59             classRequires.put(getDottedClassName(), requires);
60             requires = new TreeSet<String JavaDoc>();
61         }
62     }
63
64
65     @Override JavaDoc
66          public void sawOpcode(int seen) {
67
68
69         if (seen == PUTSTATIC && getClassConstantOperand().equals(getClassName())) {
70             // Don't do this check; it generates too many false
71
// positives. We need to do a more detailed check
72
// of which variables could be seen.
73
if (REPORT_CREATE_INSTANCE_BEFORE_FIELDS_ASSIGNED &&
74                     instanceCreated && !instanceCreatedWarningGiven) {
75                 String JavaDoc okSig = "L" + getClassName() + ";";
76                 if (!okSig.equals(getSigConstantOperand())) {
77                     bugReporter.reportBug(new BugInstance(this, "SI_INSTANCE_BEFORE_FINALS_ASSIGNED", NORMAL_PRIORITY)
78                             .addClassAndMethod(this)
79                             .addSourceLine(this, instanceCreatedPC));
80                     instanceCreatedWarningGiven = true;
81                 }
82             }
83         } else if (seen == NEW && getClassConstantOperand().equals(getClassName())) {
84             instanceCreated = true;
85             instanceCreatedPC = getPC();
86         } else if (seen == PUTSTATIC || seen == GETSTATIC || seen == INVOKESTATIC
87                 || seen == NEW)
88             if (getPC() + 6 < codeBytes.length)
89                 requires.add(getDottedClassConstantOperand());
90     }
91
92     public void compute() {
93         Set<String JavaDoc> allClasses = classRequires.keySet();
94         Set<String JavaDoc> emptyClasses = new TreeSet<String JavaDoc>();
95         for (String JavaDoc c : allClasses) {
96             Set<String JavaDoc> needs = classRequires.get(c);
97             needs.retainAll(allClasses);
98             Set<String JavaDoc> extra = new TreeSet<String JavaDoc>();
99             for (String JavaDoc need : needs)
100                 extra.addAll(classRequires.get(need));
101             needs.addAll(extra);
102             needs.retainAll(allClasses);
103             classRequires.put(c, needs);
104             if (needs.isEmpty()) emptyClasses.add(c);
105         }
106         for (String JavaDoc c : emptyClasses) {
107             classRequires.remove(c);
108         }
109     }
110
111     @Override JavaDoc
112          public void report() {
113
114         if (DEBUG) System.out.println("Finishing computation");
115         compute();
116         compute();
117         compute();
118         compute();
119         compute();
120         compute();
121         compute();
122         compute();
123         Set<String JavaDoc> allClasses = classRequires.keySet();
124
125         for (String JavaDoc c : allClasses) {
126             if (DEBUG) System.out.println("Class " + c + " requires:");
127             for (String JavaDoc needs : (classRequires.get(c))) {
128                 if (DEBUG) System.out.println(" " + needs);
129                 Set<String JavaDoc> s = classRequires.get(needs);
130                 if (s != null && s.contains(c) && c.compareTo(needs) < 0)
131                     bugReporter.reportBug(new BugInstance(this, "IC_INIT_CIRCULARITY", NORMAL_PRIORITY)
132                             .addClass(c)
133                             .addClass(needs));
134             }
135         }
136     }
137
138 }
139
Popular Tags