Source Code Cross Referenced for ClassContext.java in  » Code-Analyzer » findbugs » edu » umd » cs » findbugs » ba » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Code Analyzer » findbugs » edu.umd.cs.findbugs.ba 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Bytecode Analysis Framework
0003:         * Copyright (C) 2003-2007 University of Maryland
0004:         * 
0005:         * This library is free software; you can redistribute it and/or
0006:         * modify it under the terms of the GNU Lesser General Public
0007:         * License as published by the Free Software Foundation; either
0008:         * version 2.1 of the License, or (at your option) any later version.
0009:         * 
0010:         * This library is distributed in the hope that it will be useful,
0011:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013:         * Lesser General Public License for more details.
0014:         * 
0015:         * You should have received a copy of the GNU Lesser General Public
0016:         * License along with this library; if not, write to the Free Software
0017:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0018:         */
0019:
0020:        package edu.umd.cs.findbugs.ba;
0021:
0022:        import java.util.Arrays;
0023:        import java.util.BitSet;
0024:        import java.util.Collection;
0025:        import java.util.HashMap;
0026:        import java.util.HashSet;
0027:        import java.util.Iterator;
0028:        import java.util.List;
0029:        import java.util.Map;
0030:        import java.util.Set;
0031:        import java.util.TreeSet;
0032:
0033:        import org.apache.bcel.Constants;
0034:        import org.apache.bcel.classfile.Code;
0035:        import org.apache.bcel.classfile.JavaClass;
0036:        import org.apache.bcel.classfile.LineNumber;
0037:        import org.apache.bcel.classfile.LineNumberTable;
0038:        import org.apache.bcel.classfile.Method;
0039:        import org.apache.bcel.generic.ConstantPoolGen;
0040:        import org.apache.bcel.generic.INVOKESTATIC;
0041:        import org.apache.bcel.generic.Instruction;
0042:        import org.apache.bcel.generic.InvokeInstruction;
0043:        import org.apache.bcel.generic.MethodGen;
0044:
0045:        import edu.umd.cs.findbugs.SystemProperties;
0046:        import edu.umd.cs.findbugs.TigerSubstitutes;
0047:        import edu.umd.cs.findbugs.annotations.CheckForNull;
0048:        import edu.umd.cs.findbugs.annotations.NonNull;
0049:        import edu.umd.cs.findbugs.ba.ca.CallListDataflow;
0050:        import edu.umd.cs.findbugs.ba.constant.ConstantDataflow;
0051:        import edu.umd.cs.findbugs.ba.deref.UnconditionalValueDerefDataflow;
0052:        import edu.umd.cs.findbugs.ba.heap.LoadDataflow;
0053:        import edu.umd.cs.findbugs.ba.heap.StoreDataflow;
0054:        import edu.umd.cs.findbugs.ba.npe.IsNullValueDataflow;
0055:        import edu.umd.cs.findbugs.ba.npe.ReturnPathTypeDataflow;
0056:        import edu.umd.cs.findbugs.ba.npe.UsagesRequiringNonNullValues;
0057:        import edu.umd.cs.findbugs.ba.npe2.DefinitelyNullSetDataflow;
0058:        import edu.umd.cs.findbugs.ba.type.ExceptionSetFactory;
0059:        import edu.umd.cs.findbugs.ba.type.TypeDataflow;
0060:        import edu.umd.cs.findbugs.ba.vna.LoadedFieldSet;
0061:        import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
0062:        import edu.umd.cs.findbugs.bcel.BCELUtil;
0063:        import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
0064:        import edu.umd.cs.findbugs.classfile.ClassDescriptor;
0065:        import edu.umd.cs.findbugs.classfile.DescriptorFactory;
0066:        import edu.umd.cs.findbugs.classfile.Global;
0067:        import edu.umd.cs.findbugs.classfile.MethodDescriptor;
0068:        import edu.umd.cs.findbugs.classfile.ResourceNotFoundException;
0069:        import edu.umd.cs.findbugs.classfile.analysis.ClassInfo;
0070:        import edu.umd.cs.findbugs.classfile.engine.SelfMethodCalls;
0071:        import edu.umd.cs.findbugs.classfile.engine.bcel.NonExceptionPostdominatorsAnalysis;
0072:        import edu.umd.cs.findbugs.classfile.engine.bcel.NonImplicitExceptionPostDominatorsAnalysis;
0073:        import edu.umd.cs.findbugs.classfile.engine.bcel.UnpackedBytecodeCallback;
0074:        import edu.umd.cs.findbugs.classfile.engine.bcel.UnpackedCode;
0075:        import edu.umd.cs.findbugs.util.MapCache;
0076:        import edu.umd.cs.findbugs.util.MultiMap;
0077:        import edu.umd.cs.findbugs.util.TopologicalSort;
0078:        import edu.umd.cs.findbugs.util.TopologicalSort.OutEdges;
0079:
0080:        /**
0081:         * A ClassContext caches all of the auxiliary objects used to analyze
0082:         * the methods of a class.  That way, these objects don't need to
0083:         * be created over and over again.
0084:         *
0085:         * @author David Hovemeyer
0086:         */
0087:        public class ClassContext {
0088:            public static final boolean DEBUG = SystemProperties
0089:                    .getBoolean("classContext.debug");
0090:
0091:            public static final boolean TIME_ANALYSES = SystemProperties
0092:                    .getBoolean("classContext.timeAnalyses");
0093:
0094:            public static final boolean DUMP_DATAFLOW_ANALYSIS = SystemProperties
0095:                    .getBoolean("dataflow.dump");
0096:
0097:            public static int depth;
0098:
0099:            public static void indent() {
0100:                for (int i = 0; i < depth; ++i)
0101:                    System.out.print("  ");
0102:            }
0103:
0104:            private final JavaClass jclass;
0105:            private final ClassInfo classInfo;
0106:            private final AnalysisContext analysisContext;
0107:            private final Map<Class<?>, Map<MethodDescriptor, Object>> methodAnalysisObjectMap;
0108:
0109:            /* ----------------------------------------------------------------------
0110:             * Public methods
0111:             * ---------------------------------------------------------------------- */
0112:
0113:            /**
0114:             * Constructor.
0115:             *
0116:             * @param jclass the JavaClass
0117:             */
0118:            public ClassContext(JavaClass jclass,
0119:                    AnalysisContext analysisContext) {
0120:                this .jclass = jclass;
0121:                this .analysisContext = analysisContext;
0122:                this .methodAnalysisObjectMap = new HashMap<Class<?>, Map<MethodDescriptor, Object>>();
0123:                try {
0124:                    classInfo = (ClassInfo) Global.getAnalysisCache()
0125:                            .getClassAnalysis(
0126:                                    XClass.class,
0127:                                    DescriptorFactory
0128:                                            .createClassDescriptor(jclass));
0129:                } catch (CheckedAnalysisException e) {
0130:                    throw new AssertionError("No ClassInfo for " + jclass);
0131:                }
0132:            }
0133:
0134:            public Map<MethodDescriptor, Object> getObjectMap(
0135:                    Class<?> analysisClass) {
0136:                Map<MethodDescriptor, Object> objectMap = methodAnalysisObjectMap
0137:                        .get(analysisClass);
0138:                if (objectMap == null) {
0139:                    objectMap = new HashMap<MethodDescriptor, Object>();
0140:                    methodAnalysisObjectMap.put(analysisClass, objectMap);
0141:                }
0142:                return objectMap;
0143:            }
0144:
0145:            /**
0146:             * Store a method analysis object.
0147:             * Note that the cached analysis object could be a special value
0148:             * (indicating null or an exception).
0149:             * 
0150:             * @param analysisClass    class the method analysis object belongs to
0151:             * @param methodDescriptor method descriptor identifying the analyzed method
0152:             * @param object           the analysis object to cache
0153:             */
0154:            public void putMethodAnalysis(Class<?> analysisClass,
0155:                    MethodDescriptor methodDescriptor, Object object) {
0156:                if (object == null) {
0157:                    throw new IllegalArgumentException();
0158:                }
0159:                Map<MethodDescriptor, Object> objectMap = getObjectMap(analysisClass);
0160:                objectMap.put(methodDescriptor, object);
0161:            }
0162:
0163:            /**
0164:             * Retrieve a method analysis object.
0165:             * 
0166:             * @param analysisClass    class the method analysis object should belong to
0167:             * @param methodDescriptor method descriptor identifying the analyzed method
0168:             * @return the analysis object
0169:             * @throws CheckedAnalysisException
0170:             */
0171:            public Object getMethodAnalysis(Class<?> analysisClass,
0172:                    MethodDescriptor methodDescriptor)
0173:                    throws CheckedAnalysisException {
0174:                Map<MethodDescriptor, Object> objectMap = getObjectMap(analysisClass);
0175:                return objectMap.get(methodDescriptor);
0176:            }
0177:
0178:            public void purgeAllMethodAnalyses() {
0179:                methodAnalysisObjectMap.clear();
0180:            }
0181:
0182:            /**
0183:             * Purge all CFG-based method analyses for given method.
0184:             * 
0185:             * @param methodDescriptor method descriptor identifying method to purge
0186:             */
0187:            public void purgeMethodAnalyses(MethodDescriptor methodDescriptor) {
0188:                Set<Map.Entry<Class<?>, Map<MethodDescriptor, Object>>> entrySet = methodAnalysisObjectMap
0189:                        .entrySet();
0190:                for (Iterator<Map.Entry<Class<?>, Map<MethodDescriptor, Object>>> i = entrySet
0191:                        .iterator(); i.hasNext();) {
0192:                    Map.Entry<Class<?>, Map<MethodDescriptor, Object>> entry = i
0193:                            .next();
0194:
0195:                    Class<?> cls = entry.getKey();
0196:
0197:                    // FIXME: hack
0198:                    if (!DataflowAnalysis.class.isAssignableFrom(cls)
0199:                            && !Dataflow.class.isAssignableFrom(cls)) {
0200:                        // There is really no need to purge analysis results
0201:                        // that aren't CFG-based.
0202:                        // Currently, only dataflow analyses need
0203:                        // to be purged.
0204:                        continue;
0205:                    }
0206:
0207:                    entry.getValue().remove(methodDescriptor);
0208:                }
0209:            }
0210:
0211:            /**
0212:             * Get the JavaClass.
0213:             */
0214:            public JavaClass getJavaClass() {
0215:                return jclass;
0216:            }
0217:
0218:            public XClass getXClass() {
0219:                return classInfo;
0220:            }
0221:
0222:            public ClassDescriptor getClassDescriptor() {
0223:                return classInfo;
0224:            }
0225:
0226:            /**
0227:             * Look up the Method represented by given MethodGen.
0228:             * 
0229:             * @param methodGen a MethodGen
0230:             * @return the Method represented by the MethodGen
0231:             */
0232:            public Method getMethod(MethodGen methodGen) {
0233:                Method[] methodList = jclass.getMethods();
0234:                for (Method method : methodList) {
0235:                    if (method.getName().equals(methodGen.getName())
0236:                            && method.getSignature().equals(
0237:                                    methodGen.getSignature())
0238:                            && method.getAccessFlags() == methodGen
0239:                                    .getAccessFlags()) {
0240:                        return method;
0241:                    }
0242:                }
0243:                return null;
0244:            }
0245:
0246:            @CheckForNull
0247:            List<Method> methodsInCallOrder = null;
0248:
0249:            public @NonNull
0250:            List<Method> getMethodsInCallOrder() {
0251:                if (methodsInCallOrder != null)
0252:                    return methodsInCallOrder;
0253:                List<Method> methodList = Arrays.asList(getJavaClass()
0254:                        .getMethods());
0255:                final Map<String, Method> map = new HashMap<String, Method>();
0256:
0257:                for (Method m : methodList) {
0258:                    map.put(m.getName() + m.getSignature() + m.isStatic(), m);
0259:                }
0260:                final MultiMap<Method, Method> multiMap = SelfMethodCalls
0261:                        .getSelfCalls(getClassDescriptor(), map);
0262:                OutEdges<Method> edges1 = new OutEdges<Method>() {
0263:
0264:                    public Collection<Method> getOutEdges(Method method) {
0265:                        return multiMap.get(method);
0266:                    }
0267:                };
0268:                if (false) {
0269:                    OutEdges<Method> edges2 = new OutEdges<Method>() {
0270:                        final ConstantPoolGen cpg = getConstantPoolGen();
0271:                        final String this ClassName = getJavaClass()
0272:                                .getClassName();
0273:
0274:                        public Collection<Method> getOutEdges(Method method) {
0275:                            HashSet<Method> result = new HashSet<Method>();
0276:                            try {
0277:                                CFG cfg = getCFG(method);
0278:                                for (Iterator<Location> i = cfg
0279:                                        .locationIterator(); i.hasNext();) {
0280:                                    Instruction ins = i.next().getHandle()
0281:                                            .getInstruction();
0282:                                    if (ins instanceof  InvokeInstruction) {
0283:                                        InvokeInstruction inv = (InvokeInstruction) ins;
0284:                                        String className = inv
0285:                                                .getClassName(cpg);
0286:                                        if (!this ClassName.equals(className))
0287:                                            continue;
0288:                                        String signature = inv
0289:                                                .getSignature(cpg);
0290:                                        if (signature.indexOf('L') < 0
0291:                                                && signature.indexOf('[') < 0)
0292:                                            continue;
0293:                                        String methodKey = inv
0294:                                                .getMethodName(cpg)
0295:                                                + signature
0296:                                                + (inv instanceof  INVOKESTATIC);
0297:                                        Method method2 = map.get(methodKey);
0298:                                        if (method2 != null)
0299:                                            result.add(method2);
0300:                                    }
0301:                                }
0302:                            } catch (CFGBuilderException e) {
0303:                                AnalysisContext.logError(
0304:                                        "Error getting methods called by "
0305:                                                + this ClassName + "."
0306:                                                + method.getName() + ":"
0307:                                                + method.getSignature(), e);
0308:                            }
0309:                            return result;
0310:                        }
0311:                    };
0312:                }
0313:                methodsInCallOrder = TopologicalSort.sortByCallGraph(
0314:                        methodList, edges1);
0315:
0316:                assert methodList.size() == methodsInCallOrder.size();
0317:                return methodsInCallOrder;
0318:            }
0319:
0320:            /**
0321:             * Get the AnalysisContext.
0322:             */
0323:            public AnalysisContext getAnalysisContext() {
0324:                return analysisContext;
0325:            }
0326:
0327:            /**
0328:             * Get the RepositoryLookupFailureCallback.
0329:             *
0330:             * @return the RepositoryLookupFailureCallback
0331:             */
0332:            public RepositoryLookupFailureCallback getLookupFailureCallback() {
0333:                return analysisContext.getLookupFailureCallback();
0334:            }
0335:
0336:            /**
0337:             * Get a MethodGen object for given method.
0338:             *
0339:             * @param method the method
0340:             * @return the MethodGen object for the method, or null
0341:             *         if the method has no Code attribute (and thus cannot be analyzed)
0342:             *         or if the method seems unprofitable to analyze
0343:             */
0344:            @CheckForNull
0345:            public MethodGen getMethodGen(Method method) {
0346:                return getMethodAnalysisNoException(MethodGen.class, method);
0347:            }
0348:
0349:            /**
0350:             * Get a CFG for given method.
0351:             * If pruning options are in effect, pruning will be done.
0352:             * Because the CFG pruning can involve interprocedural analysis,
0353:             * it is done on a best-effort basis, so the CFG returned might
0354:             * not actually be pruned.
0355:             *
0356:             * @param method the method
0357:             * @return the CFG
0358:             * @throws CFGBuilderException if a CFG cannot be constructed for the method
0359:             */
0360:            public CFG getCFG(Method method) throws CFGBuilderException {
0361:                return getMethodAnalysisNoDataflowAnalysisException(CFG.class,
0362:                        method);
0363:            }
0364:
0365:            /**
0366:             * Get the ConstantPoolGen used to create the MethodGens
0367:             * for this class.
0368:             *
0369:             * @return the ConstantPoolGen
0370:             */
0371:            public @NonNull
0372:            ConstantPoolGen getConstantPoolGen() {
0373:                return getClassAnalysisNoException(ConstantPoolGen.class);
0374:            }
0375:
0376:            /**
0377:             * Get a UsagesRequiringNonNullValues for given method.
0378:             *
0379:             * @param method the method
0380:             * @return the UsagesRequiringNonNullValues
0381:             */
0382:            public UsagesRequiringNonNullValues getUsagesRequiringNonNullValues(
0383:                    Method method) throws DataflowAnalysisException,
0384:                    CFGBuilderException {
0385:                return getMethodAnalysis(UsagesRequiringNonNullValues.class,
0386:                        method);
0387:            }
0388:
0389:            /**
0390:             * Get a ValueNumberDataflow for given method.
0391:             *
0392:             * @param method the method
0393:             * @return the ValueNumberDataflow
0394:             */
0395:            public ValueNumberDataflow getValueNumberDataflow(Method method)
0396:                    throws DataflowAnalysisException, CFGBuilderException {
0397:                return getMethodAnalysis(ValueNumberDataflow.class, method);
0398:            }
0399:
0400:            /**
0401:             * Get an IsNullValueDataflow for given method.
0402:             *
0403:             * @param method the method
0404:             * @return the IsNullValueDataflow
0405:             */
0406:            public IsNullValueDataflow getIsNullValueDataflow(Method method)
0407:                    throws DataflowAnalysisException, CFGBuilderException {
0408:                return getMethodAnalysis(IsNullValueDataflow.class, method);
0409:            }
0410:
0411:            /**
0412:             * Get a TypeDataflow for given method.
0413:             *
0414:             * @param method the method
0415:             * @return the TypeDataflow
0416:             */
0417:            public TypeDataflow getTypeDataflow(Method method)
0418:                    throws DataflowAnalysisException, CFGBuilderException {
0419:                return getMethodAnalysis(TypeDataflow.class, method);
0420:            }
0421:
0422:            /**
0423:             * Get a DepthFirstSearch for given method.
0424:             *
0425:             * @param method the method
0426:             * @return the DepthFirstSearch
0427:             */
0428:            public DepthFirstSearch getDepthFirstSearch(Method method)
0429:                    throws CFGBuilderException {
0430:                return getMethodAnalysisNoDataflowAnalysisException(
0431:                        DepthFirstSearch.class, method);
0432:            }
0433:
0434:            /**
0435:             * Get a ReverseDepthFirstSearch for given method.
0436:             *
0437:             * @param method the method
0438:             * @return the ReverseDepthFirstSearch
0439:             */
0440:            public ReverseDepthFirstSearch getReverseDepthFirstSearch(
0441:                    Method method) throws CFGBuilderException {
0442:                return getMethodAnalysisNoDataflowAnalysisException(
0443:                        ReverseDepthFirstSearch.class, method);
0444:            }
0445:
0446:            static MapCache<XMethod, BitSet> cachedBitsets = new MapCache<XMethod, BitSet>(
0447:                    64);
0448:            static MapCache<XMethod, Set<Integer>> cachedLoopExits = new MapCache<XMethod, Set<Integer>>(
0449:                    13);
0450:
0451:            /**
0452:             * Get a BitSet representing the bytecodes that are used in the given method.
0453:             * This is useful for prescreening a method for the existence of particular instructions.
0454:             * Because this step doesn't require building a MethodGen, it is very
0455:             * fast and memory-efficient.  It may allow a Detector to avoid some
0456:             * very expensive analysis, which is a Big Win for the user.
0457:             *
0458:             * @param method the method
0459:             * @return the BitSet containing the opcodes which appear in the method,
0460:             *          or null if the method has no code
0461:             */
0462:            @CheckForNull
0463:            public BitSet getBytecodeSet(Method method) {
0464:                return getBytecodeSet(jclass, method);
0465:            }
0466:
0467:            /**
0468:             * Get a BitSet representing the bytecodes that are used in the given method.
0469:             * This is useful for prescreening a method for the existence of particular instructions.
0470:             * Because this step doesn't require building a MethodGen, it is very
0471:             * fast and memory-efficient.  It may allow a Detector to avoid some
0472:             * very expensive analysis, which is a Big Win for the user.
0473:             *
0474:             * @param method the method
0475:             * @return the BitSet containing the opcodes which appear in the method,
0476:             *          or null if the method has no code
0477:             */
0478:            @CheckForNull
0479:            static public BitSet getBytecodeSet(JavaClass clazz, Method method) {
0480:
0481:                XMethod xmethod = XFactory.createXMethod(clazz, method);
0482:                if (cachedBitsets.containsKey(xmethod)) {
0483:                    return cachedBitsets.get(xmethod);
0484:                }
0485:                Code code = method.getCode();
0486:                if (code == null)
0487:                    return null;
0488:
0489:                byte[] instructionList = code.getCode();
0490:
0491:                // Create callback
0492:                UnpackedBytecodeCallback callback = new UnpackedBytecodeCallback(
0493:                        instructionList.length);
0494:
0495:                // Scan the method.
0496:                BytecodeScanner scanner = new BytecodeScanner();
0497:                scanner.scan(instructionList, callback);
0498:
0499:                UnpackedCode unpackedCode = callback.getUnpackedCode();
0500:                BitSet result = null;
0501:                if (unpackedCode != null)
0502:                    result = unpackedCode.getBytecodeSet();
0503:                cachedBitsets.put(xmethod, result);
0504:                return result;
0505:            }
0506:
0507:            @CheckForNull
0508:            static public Set<Integer> getLoopExitBranches(Method method,
0509:                    MethodGen methodGen) {
0510:
0511:                XMethod xmethod = XFactory.createXMethod(methodGen);
0512:                if (cachedLoopExits.containsKey(xmethod)) {
0513:                    return cachedLoopExits.get(xmethod);
0514:                }
0515:                Code code = method.getCode();
0516:                if (code == null)
0517:                    return null;
0518:
0519:                byte[] instructionList = code.getCode();
0520:
0521:                Set<Integer> result = new HashSet<Integer>();
0522:                for (int i = 0; i < instructionList.length; i++)
0523:                    if (checkForBranchExit(instructionList, i))
0524:                        result.add(i);
0525:                if (result.size() == 0)
0526:                    result = TigerSubstitutes.emptySet(); // alas, emptySet() is @since 1.5
0527:
0528:                cachedLoopExits.put(xmethod, result);
0529:                return result;
0530:            }
0531:
0532:            static short getBranchOffset(byte[] codeBytes, int pos) {
0533:                int branchByte1 = 0xff & codeBytes[pos];
0534:                int branchByte2 = 0xff & codeBytes[pos + 1];
0535:                int branchOffset = (short) (branchByte1 << 8 | branchByte2);
0536:                return (short) branchOffset;
0537:
0538:            }
0539:
0540:            static boolean checkForBranchExit(byte[] codeBytes, int pos) {
0541:                if (pos < 0 || pos + 2 >= codeBytes.length)
0542:                    return false;
0543:                switch (0xff & codeBytes[pos]) {
0544:                case Constants.IF_ACMPEQ:
0545:                case Constants.IF_ACMPNE:
0546:                case Constants.IF_ICMPEQ:
0547:                case Constants.IF_ICMPGE:
0548:                case Constants.IF_ICMPGT:
0549:                case Constants.IF_ICMPLE:
0550:                case Constants.IF_ICMPLT:
0551:                case Constants.IF_ICMPNE:
0552:                    break;
0553:                default:
0554:                    return false;
0555:                }
0556:                int branchTarget = pos + getBranchOffset(codeBytes, pos + 1);
0557:                if (branchTarget - 3 < pos || branchTarget >= codeBytes.length)
0558:                    return false;
0559:                if ((codeBytes[branchTarget - 3] & 0xff) != Constants.GOTO)
0560:                    return false;
0561:                int backBranchTarget = branchTarget
0562:                        + getBranchOffset(codeBytes, branchTarget - 2);
0563:                if (backBranchTarget <= pos && backBranchTarget + 12 >= pos)
0564:                    return true;
0565:                return false;
0566:            }
0567:
0568:            /**
0569:             * Get array mapping bytecode offsets to opcodes for given method.
0570:             * Array elements containing zero are either not valid instruction offsets,
0571:             * or contain a NOP instruction.  (It is convenient not to distinguish
0572:             * these cases.)
0573:             * 
0574:             * @param method the method
0575:             * @return map of bytecode offsets to opcodes, or null if the method has no code
0576:             */
0577:            public short[] getOffsetToOpcodeMap(Method method) {
0578:                UnpackedCode unpackedCode = getMethodAnalysisNoException(
0579:                        UnpackedCode.class, method);
0580:                return unpackedCode != null ? unpackedCode
0581:                        .getOffsetToBytecodeMap() : null;
0582:            }
0583:
0584:            /**
0585:             * Get dataflow for LockAnalysis for given method.
0586:             *
0587:             * @param method the method
0588:             * @return the LockDataflow
0589:             */
0590:            public LockDataflow getLockDataflow(Method method)
0591:                    throws CFGBuilderException, DataflowAnalysisException {
0592:                return getMethodAnalysis(LockDataflow.class, method);
0593:            }
0594:
0595:            /**
0596:             * Get LockChecker for method.
0597:             * This is like LockDataflow, but may be able to avoid performing
0598:             * the actual dataflow analyses if the method doesn't contain
0599:             * explicit monitorenter/monitorexit instructions.
0600:             * 
0601:             * @param method the method
0602:             * @return the LockChecker
0603:             * @throws CFGBuilderException
0604:             * @throws DataflowAnalysisException
0605:             */
0606:            public LockChecker getLockChecker(Method method)
0607:                    throws CFGBuilderException, DataflowAnalysisException {
0608:                return getMethodAnalysis(LockChecker.class, method);
0609:            }
0610:
0611:            /**
0612:             * Get ReturnPathDataflow for method.
0613:             *
0614:             * @param method the method
0615:             * @return the ReturnPathDataflow
0616:             */
0617:            public ReturnPathDataflow getReturnPathDataflow(Method method)
0618:                    throws CFGBuilderException, DataflowAnalysisException {
0619:                return getMethodAnalysis(ReturnPathDataflow.class, method);
0620:            }
0621:
0622:            /**
0623:             * Get DominatorsAnalysis for given method,
0624:             * where exception edges are ignored.
0625:             *
0626:             * @param method the method
0627:             * @return the DominatorsAnalysis
0628:             */
0629:            public DominatorsAnalysis getNonExceptionDominatorsAnalysis(
0630:                    Method method) throws CFGBuilderException,
0631:                    DataflowAnalysisException {
0632:                return getMethodAnalysis(DominatorsAnalysis.class, method);
0633:            }
0634:
0635:            /**
0636:             * Get DominatorsAnalysis for given method,
0637:             * where implicit exception edges are ignored.
0638:             *
0639:             * @param method the method
0640:             * @return the DominatorsAnalysis
0641:             */
0642:            public PostDominatorsAnalysis getNonImplicitExceptionDominatorsAnalysis(
0643:                    Method method) throws CFGBuilderException,
0644:                    DataflowAnalysisException {
0645:                return getMethodAnalysis(
0646:                        NonImplicitExceptionPostDominatorsAnalysis.class,
0647:                        method);
0648:            }
0649:
0650:            /**
0651:             * Get PostDominatorsAnalysis for given method,
0652:             * where exception edges are ignored.
0653:             *
0654:             * @param method the method
0655:             * @return the PostDominatorsAnalysis
0656:             */
0657:            public PostDominatorsAnalysis getNonExceptionPostDominatorsAnalysis(
0658:                    Method method) throws CFGBuilderException,
0659:                    DataflowAnalysisException {
0660:                return getMethodAnalysis(
0661:                        NonExceptionPostdominatorsAnalysis.class, method);
0662:            }
0663:
0664:            /**
0665:             * Get ExceptionSetFactory for given method.
0666:             *
0667:             * @param method the method
0668:             * @return the ExceptionSetFactory
0669:             */
0670:            public ExceptionSetFactory getExceptionSetFactory(Method method) {
0671:                return getMethodAnalysisNoException(ExceptionSetFactory.class,
0672:                        method);
0673:            }
0674:
0675:            /**
0676:             * Get array of type signatures of parameters for given method.
0677:             *
0678:             * @param method the method
0679:             * @return an array of type signatures indicating the types
0680:             *         of the method's parameters
0681:             */
0682:            public String[] getParameterSignatureList(Method method) {
0683:                return getMethodAnalysisNoException(
0684:                        (Class<String[]>) new String[0].getClass(), method);// XXX
0685:            }
0686:
0687:            /**
0688:             * Get the set of fields loaded by given method.
0689:             *
0690:             * @param method the method
0691:             * @return the set of fields loaded by the method
0692:             */
0693:            public LoadedFieldSet getLoadedFieldSet(Method method) {
0694:                return getMethodAnalysisNoException(LoadedFieldSet.class,
0695:                        method);
0696:            }
0697:
0698:            /**
0699:             * Get LiveLocalStoreAnalysis dataflow for given method.
0700:             *
0701:             * @param method the method
0702:             * @return the Dataflow object for LiveLocalStoreAnalysis on the method
0703:             */
0704:            public LiveLocalStoreDataflow getLiveLocalStoreDataflow(
0705:                    Method method) throws DataflowAnalysisException,
0706:                    CFGBuilderException {
0707:                return getMethodAnalysis(LiveLocalStoreDataflow.class, method);
0708:            }
0709:
0710:            /**
0711:             * Get BlockType dataflow for given method.
0712:             *
0713:             * @param method the method
0714:             * @return the Dataflow object for BlockTypeAnalysis on the method
0715:             */
0716:            public BlockTypeDataflow getBlockTypeDataflow(Method method)
0717:                    throws DataflowAnalysisException, CFGBuilderException {
0718:                return getMethodAnalysis(BlockTypeDataflow.class, method);
0719:            }
0720:
0721:            //	/**
0722:            //	 * Get the assigned field map for the class.
0723:            //	 *
0724:            //	 * @return the AssignedFieldMap
0725:            //	 * @throws ClassNotFoundException if a class lookup prevents
0726:            //	 *                                the class's superclasses from being searched for
0727:            //	 *                                assignable fields
0728:            //	 */
0729:            //	public AssignedFieldMap getAssignedFieldMap() throws ClassNotFoundException {
0730:            //		return getClassAnalysisPossibleClassNotFoundException(AssignedFieldMap.class);
0731:            //	}
0732:
0733:            /**
0734:             * Get AssertionMethods for class.
0735:             *
0736:             * @return the AssertionMethods
0737:             */
0738:            public AssertionMethods getAssertionMethods() {
0739:                return getClassAnalysisNoException(AssertionMethods.class);
0740:            }
0741:
0742:            /**
0743:             * Get ConstantDataflow for method.
0744:             * 
0745:             * @param method the method
0746:             * @return the ConstantDataflow
0747:             * @throws CFGBuilderException
0748:             * @throws DataflowAnalysisException
0749:             */
0750:            public ConstantDataflow getConstantDataflow(Method method)
0751:                    throws CFGBuilderException, DataflowAnalysisException {
0752:                return getMethodAnalysis(ConstantDataflow.class, method);
0753:            }
0754:
0755:            /**
0756:             * Get load dataflow.
0757:             * 
0758:             * @param method the method
0759:             * @return the LoadDataflow
0760:             * @throws CFGBuilderException
0761:             * @throws DataflowAnalysisException
0762:             */
0763:            public LoadDataflow getLoadDataflow(Method method)
0764:                    throws CFGBuilderException, DataflowAnalysisException {
0765:                return getMethodAnalysis(LoadDataflow.class, method);
0766:            }
0767:
0768:            /**
0769:             * Get store dataflow.
0770:             * 
0771:             * @param method the method
0772:             * @return the StoreDataflow
0773:             * @throws CFGBuilderException
0774:             * @throws DataflowAnalysisException
0775:             */
0776:            public StoreDataflow getStoreDataflow(Method method)
0777:                    throws CFGBuilderException, DataflowAnalysisException {
0778:                return getMethodAnalysis(StoreDataflow.class, method);
0779:            }
0780:
0781:            /**
0782:             * Get CallListDataflow for method.
0783:             * 
0784:             * @param method the method
0785:             * @return the CallListDataflow
0786:             * @throws CFGBuilderException
0787:             * @throws DataflowAnalysisException
0788:             */
0789:            public CallListDataflow getCallListDataflow(Method method)
0790:                    throws CFGBuilderException, DataflowAnalysisException {
0791:                return getMethodAnalysis(CallListDataflow.class, method);
0792:            }
0793:
0794:            public static BitSet linesMentionedMultipleTimes(Method method) {
0795:
0796:                BitSet lineMentionedMultipleTimes = new BitSet();
0797:                Code code = method.getCode();
0798:                if (code == null || code.getExceptionTable() == null)
0799:                    return lineMentionedMultipleTimes;
0800:                BitSet foundOnce = new BitSet();
0801:                LineNumberTable lineNumberTable = method.getLineNumberTable();
0802:                int lineNum = -1;
0803:                if (lineNumberTable != null)
0804:                    for (LineNumber line : lineNumberTable.getLineNumberTable()) {
0805:                        int newLine = line.getLineNumber();
0806:                        if (newLine == lineNum || newLine == -1)
0807:                            continue;
0808:                        lineNum = newLine;
0809:                        if (foundOnce.get(lineNum)) {
0810:                            lineMentionedMultipleTimes.set(lineNum);
0811:                        } else {
0812:                            foundOnce.set(lineNum);
0813:                        }
0814:                    }
0815:                return lineMentionedMultipleTimes;
0816:            }
0817:
0818:            /**
0819:             * Get the UnconditionalValueDerefDataflow for a method.
0820:             * 
0821:             * @param method the method
0822:             * @return the UnconditionalValueDerefDataflow 
0823:             * @throws CFGBuilderException
0824:             * @throws DataflowAnalysisException
0825:             */
0826:            public UnconditionalValueDerefDataflow getUnconditionalValueDerefDataflow(
0827:                    Method method) throws CFGBuilderException,
0828:                    DataflowAnalysisException {
0829:                return getMethodAnalysis(UnconditionalValueDerefDataflow.class,
0830:                        method);
0831:            }
0832:
0833:            /**
0834:             * Get a CompactLocationNumbering for a method.
0835:             * 
0836:             * @param method a method
0837:             * @return the CompactLocationNumbering for the method
0838:             * @throws CFGBuilderException
0839:             */
0840:            public CompactLocationNumbering getCompactLocationNumbering(
0841:                    Method method) throws CFGBuilderException {
0842:                return getMethodAnalysisNoDataflowAnalysisException(
0843:                        CompactLocationNumbering.class, method);
0844:            }
0845:
0846:            /**
0847:             * Get DefinitelyNullSetDataflow for a method.
0848:             * 
0849:             * @param method a method
0850:             * @return the DefinitelyNullSetDataflow for the method 
0851:             * @throws DataflowAnalysisException 
0852:             * @throws CFGBuilderException 
0853:             */
0854:            public DefinitelyNullSetDataflow getDefinitelyNullSetDataflow(
0855:                    Method method) throws CFGBuilderException,
0856:                    DataflowAnalysisException {
0857:                return getMethodAnalysis(DefinitelyNullSetDataflow.class,
0858:                        method);
0859:            }
0860:
0861:            /**
0862:             * Get ReturnPathTypeDataflow for a method.
0863:             * 
0864:             * @param method the method
0865:             * @return the ReturnPathTypeDataflow for the method
0866:             * @throws CFGBuilderException
0867:             * @throws DataflowAnalysisException
0868:             */
0869:            public ReturnPathTypeDataflow getReturnPathTypeDataflow(
0870:                    Method method) throws CFGBuilderException,
0871:                    DataflowAnalysisException {
0872:                return getMethodAnalysis(ReturnPathTypeDataflow.class, method);
0873:            }
0874:
0875:            public void dumpSimpleDataflowInformation(Method method) {
0876:                try {
0877:                    dumpDataflowInformation(method, getCFG(method),
0878:                            getValueNumberDataflow(method),
0879:                            getIsNullValueDataflow(method), null, null);
0880:                } catch (DataflowAnalysisException e) {
0881:                    AnalysisContext.logError(
0882:                            "Could not dump data information for "
0883:                                    + getJavaClass().getClassName() + "."
0884:                                    + method.getName(), e);
0885:                } catch (CFGBuilderException e) {
0886:                    AnalysisContext.logError(
0887:                            "Could not dump data information for "
0888:                                    + getJavaClass().getClassName() + "."
0889:                                    + method.getName(), e);
0890:
0891:                }
0892:            }
0893:
0894:            public void dumpDataflowInformation(Method method) {
0895:                try {
0896:                    dumpDataflowInformation(method, getCFG(method),
0897:                            getValueNumberDataflow(method),
0898:                            getIsNullValueDataflow(method),
0899:                            getUnconditionalValueDerefDataflow(method),
0900:                            getTypeDataflow(method));
0901:                } catch (DataflowAnalysisException e) {
0902:                    AnalysisContext.logError(
0903:                            "Could not dump data information for "
0904:                                    + getJavaClass().getClassName() + "."
0905:                                    + method.getName(), e);
0906:                } catch (CFGBuilderException e) {
0907:                    AnalysisContext.logError(
0908:                            "Could not dump data information for "
0909:                                    + getJavaClass().getClassName() + "."
0910:                                    + method.getName(), e);
0911:
0912:                }
0913:            }
0914:
0915:            /**
0916:             * @param method
0917:             * @param cfg
0918:             * @param vnd
0919:             * @param inv
0920:             * @param dataflow
0921:             * @param typeDataflow TODO
0922:             * @throws DataflowAnalysisException
0923:             */
0924:            public static void dumpDataflowInformation(Method method, CFG cfg,
0925:                    ValueNumberDataflow vnd, IsNullValueDataflow inv,
0926:                    @CheckForNull
0927:                    UnconditionalValueDerefDataflow dataflow, @CheckForNull
0928:                    TypeDataflow typeDataflow) throws DataflowAnalysisException {
0929:                System.out
0930:                        .println("\n\n{ UnconditionalValueDerefAnalysis analysis for "
0931:                                + method.getName());
0932:                TreeSet<Location> tree = new TreeSet<Location>();
0933:
0934:                for (Iterator<Location> locs = cfg.locationIterator(); locs
0935:                        .hasNext();) {
0936:                    Location loc = locs.next();
0937:                    tree.add(loc);
0938:                }
0939:                for (Location loc : tree) {
0940:                    System.out.println();
0941:                    if (dataflow != null)
0942:                        System.out.println("\n Pre: "
0943:                                + dataflow.getFactAfterLocation(loc));
0944:                    System.out.println("Vna: " + vnd.getFactAtLocation(loc));
0945:                    System.out.println("inv: " + inv.getFactAtLocation(loc));
0946:                    if (typeDataflow != null)
0947:                        System.out.println("type: "
0948:                                + typeDataflow.getFactAtLocation(loc));
0949:                    System.out.println("Location: " + loc);
0950:                    if (dataflow != null)
0951:                        System.out.println("Post: "
0952:                                + dataflow.getFactAtLocation(loc));
0953:                    System.out.println("Vna: " + vnd.getFactAfterLocation(loc));
0954:                    System.out.println("inv: " + inv.getFactAfterLocation(loc));
0955:                    if (typeDataflow != null)
0956:                        System.out.println("type: "
0957:                                + typeDataflow.getFactAfterLocation(loc));
0958:                }
0959:                System.out.println("}\n\n");
0960:            }
0961:
0962:            /**
0963:             * @param method
0964:             * @param cfg
0965:             * @param typeDataflow
0966:             * @throws DataflowAnalysisException
0967:             */
0968:            public static void dumpTypeDataflow(Method method, CFG cfg,
0969:                    TypeDataflow typeDataflow) throws DataflowAnalysisException {
0970:                System.out.println("\n\n{ Type analysis for "
0971:                        + cfg.getMethodGen().getClassName() + "."
0972:                        + method.getName());
0973:                TreeSet<Location> tree = new TreeSet<Location>();
0974:
0975:                for (Iterator<Location> locs = cfg.locationIterator(); locs
0976:                        .hasNext();) {
0977:                    Location loc = locs.next();
0978:                    tree.add(loc);
0979:                }
0980:                for (Location loc : tree) {
0981:                    System.out.println("\n Pre: "
0982:                            + typeDataflow.getFactAtLocation(loc));
0983:                    System.out.println("Location: " + loc);
0984:                    System.out.println("Post: "
0985:                            + typeDataflow.getFactAfterLocation(loc));
0986:                }
0987:                System.out.println("}\n\n");
0988:            }
0989:
0990:            /* ----------------------------------------------------------------------
0991:             * Helper methods for getting an analysis object from the analysis cache.
0992:             * ---------------------------------------------------------------------- */
0993:
0994:            private <Analysis> Analysis getMethodAnalysisNoException(
0995:                    Class<Analysis> analysisClass, Method method) {
0996:                try {
0997:                    return getMethodAnalysis(analysisClass, method);
0998:                } catch (CheckedAnalysisException e) {
0999:                    IllegalStateException ise = new IllegalStateException(
1000:                            "should not happen");
1001:                    ise.initCause(e);
1002:                    throw ise;
1003:                }
1004:            }
1005:
1006:            private <Analysis> Analysis getMethodAnalysisNoDataflowAnalysisException(
1007:                    Class<Analysis> analysisClass, Method method)
1008:                    throws CFGBuilderException {
1009:                try {
1010:                    return getMethodAnalysis(analysisClass, method);
1011:                } catch (CFGBuilderException e) {
1012:                    throw e;
1013:                } catch (CheckedAnalysisException e) {
1014:                    IllegalStateException ise = new IllegalStateException(
1015:                            "should not happen");
1016:                    ise.initCause(e);
1017:                    throw ise;
1018:                }
1019:
1020:            }
1021:
1022:            private <Analysis> Analysis getMethodAnalysis(
1023:                    Class<Analysis> analysisClass, Method method)
1024:                    throws DataflowAnalysisException, CFGBuilderException {
1025:                try {
1026:                    MethodDescriptor methodDescriptor = BCELUtil
1027:                            .getMethodDescriptor(jclass, method);
1028:                    return Global.getAnalysisCache().getMethodAnalysis(
1029:                            analysisClass, methodDescriptor);
1030:                } catch (DataflowAnalysisException e) {
1031:                    throw e;
1032:                } catch (CFGBuilderException e) {
1033:                    throw e;
1034:                } catch (CheckedAnalysisException e) {
1035:                    Throwable cause = e.getCause();
1036:                    if (cause instanceof  CFGBuilderException) {
1037:                        throw (CFGBuilderException) cause;
1038:                    }
1039:                    System.out.println("Bad CAE: " + e.getClass().getName()
1040:                            + " for " + analysisClass.getName() + " of "
1041:                            + method);
1042:                    e.printStackTrace(System.out);
1043:                    IllegalStateException ise = new IllegalStateException(
1044:                            "should not happen");
1045:                    ise.initCause(e);
1046:                    throw ise;
1047:                }
1048:            }
1049:
1050:            private <Analysis> Analysis getClassAnalysis(
1051:                    Class<Analysis> analysisClass)
1052:                    throws CheckedAnalysisException {
1053:                ClassDescriptor classDescriptor = BCELUtil
1054:                        .getClassDescriptor(jclass);
1055:                return Global.getAnalysisCache().getClassAnalysis(
1056:                        analysisClass, classDescriptor);
1057:            }
1058:
1059:            private <Analysis> Analysis getClassAnalysisNoException(
1060:                    Class<Analysis> analysisClass) {
1061:                try {
1062:                    return getClassAnalysis(analysisClass);
1063:                } catch (CheckedAnalysisException e) {
1064:                    IllegalStateException ise = new IllegalStateException(
1065:                            "should not happen");
1066:                    ise.initCause(e);
1067:                    throw ise;
1068:                }
1069:            }
1070:
1071:            private <Analysis> Analysis getClassAnalysisPossibleClassNotFoundException(
1072:                    Class<Analysis> analysisClass)
1073:                    throws ClassNotFoundException {
1074:                try {
1075:                    return Global.getAnalysisCache().getClassAnalysis(
1076:                            analysisClass, BCELUtil.getClassDescriptor(jclass));
1077:                } catch (ResourceNotFoundException e) {
1078:                    throw e.toClassNotFoundException();
1079:                } catch (CheckedAnalysisException e) {
1080:                    throw new AnalysisException("Unexpected exception", e);
1081:                }
1082:            }
1083:        }
1084:
1085:        // vim:ts=3
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.