📄 classcontext.java
字号:
@Override protected CompactLocationNumbering analyze(Method method) throws CFGBuilderException, DataflowAnalysisException { if (method.getCode() == null) { return null; } CFG cfg = getCFG(method); return new CompactLocationNumbering(cfg); } }; private DataflowAnalysisFactory<DefinitelyNullSetDataflow> definitelyNullSetDataflowFactory = new DataflowAnalysisFactory<DefinitelyNullSetDataflow>("definitely null set dataflow") { /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.ClassContext.AnalysisFactory#analyze(org.apache.bcel.classfile.Method) */ @Override protected DefinitelyNullSetDataflow analyze(Method method) throws CFGBuilderException, DataflowAnalysisException { CFG cfg = getCFG(method); DepthFirstSearch dfs = getDepthFirstSearch(method); ValueNumberDataflow vnaDataflow = getValueNumberDataflow(method); CompactLocationNumbering compactLocationNumbering = getCompactLocationNumbering(method); DefinitelyNullSetAnalysis analysis = new DefinitelyNullSetAnalysis(dfs, vnaDataflow, compactLocationNumbering); DefinitelyNullSetDataflow dataflow = new DefinitelyNullSetDataflow(cfg, analysis); dataflow.execute(); return dataflow; } }; private DataflowAnalysisFactory<ReturnPathTypeDataflow> returnPathTypeDataflowFactory = new DataflowAnalysisFactory<ReturnPathTypeDataflow>("return path type dataflow") { /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.ClassContext.AnalysisFactory#analyze(org.apache.bcel.classfile.Method) */ @Override protected ReturnPathTypeDataflow analyze(Method method) throws CFGBuilderException, DataflowAnalysisException { CFG cfg = getCFG(method); DepthFirstSearch dfs = getDepthFirstSearch(method); ReverseDepthFirstSearch rdfs = getReverseDepthFirstSearch(method); ReturnPathTypeAnalysis analysis = new ReturnPathTypeAnalysis(cfg, rdfs, dfs); ReturnPathTypeDataflow dataflow = new ReturnPathTypeDataflow(cfg, analysis); dataflow.execute(); return dataflow; } }; private ClassGen classGen; private AssignedFieldMap assignedFieldMap; private AssertionMethods assertionMethods; /* ---------------------------------------------------------------------- * Public methods * ---------------------------------------------------------------------- */ /** * Constructor. * * @param jclass the JavaClass */ public ClassContext(JavaClass jclass, AnalysisContext analysisContext) { this.jclass = jclass; this.analysisContext = analysisContext; this.classGen = null; this.assignedFieldMap = null; this.assertionMethods = null; } /** * Purge dataflow analysis results after CFG-pruning of given method. * * @param method the method whose CFG has just been pruned */ void purgeAnalysisResultsAfterCFGPruning(Method method) { for (AnalysisFactory<?> factory : analysisFactoryList) { if (factory.isDataflow()) { factory.purge(method); } } } /** * Get the JavaClass. */ public JavaClass getJavaClass() { return jclass; } /** * Look up the Method represented by given MethodGen. * * @param methodGen a MethodGen * @return the Method represented by the MethodGen */ public Method getMethod(MethodGen methodGen) { Method[] methodList = jclass.getMethods(); for (Method method : methodList) { if (method.getName().equals(methodGen.getName()) && method.getSignature().equals(methodGen.getSignature()) && method.getAccessFlags() == methodGen.getAccessFlags()) { return method; } } return null; } @CheckForNull List<Method> methodsInCallOrder = null; public @NonNull List<Method> getMethodsInCallOrder() { if (methodsInCallOrder != null) return methodsInCallOrder; List<Method> methodList = Arrays.asList(getJavaClass().getMethods()); final Map<String, Method> map = new HashMap<String, Method>(); for (Method m : methodList) { map.put(m.getName() + m.getSignature(), m); } final ConstantPoolGen cpg = getConstantPoolGen(); final String thisClassName = getJavaClass().getClassName(); methodsInCallOrder = TopologicalSort.sortByCallGraph(methodList, new OutEdges<Method>() { public Collection<Method> getOutEdges(Method method) { HashSet<Method> result = new HashSet<Method>(); try { CFG cfg = getCFG(method); for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) { Instruction ins = i.next().getHandle().getInstruction(); if (ins instanceof InvokeInstruction) { InvokeInstruction inv = (InvokeInstruction) ins; String className = inv.getClassName(cpg); if (!thisClassName.equals(className)) continue; String signature = inv.getSignature(cpg); if (signature.indexOf('L') < 0 && signature.indexOf('[') < 0) continue; String methodKey = inv.getMethodName(cpg) + signature; Method method2 = map.get(methodKey); if (method2 != null) result.add(method2); } } } catch (CFGBuilderException e) { AnalysisContext.logError("Error getting methods called by " + thisClassName + "." + method.getName() + ":" + method.getSignature(), e); } return result; } }); assert methodList.size() == methodsInCallOrder.size(); return methodsInCallOrder; } /** * Get the AnalysisContext. */ public AnalysisContext getAnalysisContext() { return analysisContext; } /** * Get the RepositoryLookupFailureCallback. * * @return the RepositoryLookupFailureCallback */ public RepositoryLookupFailureCallback getLookupFailureCallback() { return analysisContext.getLookupFailureCallback(); } /** * Get a MethodGen object for given method. * * @param method the method * @return the MethodGen object for the method, or null * if the method has no Code attribute (and thus cannot be analyzed) * or if the method seems unprofitable to analyze */ @CheckForNull public MethodGen getMethodGen(Method method) { return methodGenFactory.getAnalysis(method); } /** * Get a "raw" CFG for given method. * No pruning is done, although the CFG may already be pruned. * * @param method the method * @return the raw CFG */ public CFG getRawCFG(Method method) throws CFGBuilderException { return cfgFactory.getRawCFG(method); } /** * Get a CFG for given method. * If pruning options are in effect, pruning will be done. * Because the CFG pruning can involve interprocedural analysis, * it is done on a best-effort basis, so the CFG returned might * not actually be pruned. * * @param method the method * @return the CFG * @throws CFGBuilderException if a CFG cannot be constructed for the method */ public CFG getCFG(Method method) throws CFGBuilderException { if (method == cachedMethod) { // System.out.println("hit on " + method.getName()); return cachedCFG; } if (false && cachedMethod != null) System.out.println(cachedMethod.getName() + " -> " + method.getName()); CFG cfg = cfgFactory.getRefinedCFG(method); cachedMethod = method; cachedCFG = cfg; return cfg; } Method cachedMethod; CFG cachedCFG = null; /** * Get the ConstantPoolGen used to create the MethodGens * for this class. * * @return the ConstantPoolGen */ public @NonNull ConstantPoolGen getConstantPoolGen() { if (classGen == null) classGen = new ClassGen(jclass); return classGen.getConstantPool(); } /** * Get a UsagesRequiringNonNullValues for given method. * * @param method the method * @return the UsagesRequiringNonNullValues */ public UsagesRequiringNonNullValues getUsagesRequiringNonNullValues(Method method) throws DataflowAnalysisException, CFGBuilderException { return derefFactory.getAnalysis(method); } /** * Get a ValueNumberDataflow for given method. * * @param method the method * @return the ValueNumberDataflow */ public ValueNumberDataflow getValueNumberDataflow(Method method) throws DataflowAnalysisException, CFGBuilderException { return vnaDataflowFactory.getAnalysis(method); } /** * Get an IsNullValueDataflow for given method. * * @param method the method * @return the IsNullValueDataflow */ public IsNullValueDataflow getIsNullValueDataflow(Method method) throws DataflowAnalysisException, CFGBuilderException { return invDataflowFactory.getAnalysis(method); } /** * Get a TypeDataflow for given method. * * @param method the method * @return the TypeDataflow */ public TypeDataflow getTypeDataflow(Method method) throws DataflowAnalysisException, CFGBuilderException { return typeDataflowFactory.getAnalysis(method); } /** * Get a DepthFirstSearch for given method. * * @param method the method * @return the DepthFirstSearch */ public DepthFirstSearch getDepthFirstSearch(Method method) throws CFGBuilderException { return dfsFactory.getAnalysis(method); } /** * Get a ReverseDepthFirstSearch for given method. * * @param method the method * @return the ReverseDepthFirstSearch */ public ReverseDepthFirstSearch getReverseDepthFirstSearch(Method method) throws CFGBuilderException { return rdfsFactory.getAnalysis(method); } static MapCache<XMethod,BitSet> cachedBitsets = new MapCache<XMethod, BitSet>(64); static MapCache<XMethod,Set<Integer>> cachedLoopExits = new MapCache<XMethod, Set<Integer>>(13); /** * Get a BitSet representing the bytecodes that are used in the given method. * This is useful for prescreening a method for the existence of particular instructions. * Because this step doesn't require building a MethodGen, it is very * fast and memory-efficient. It may allow a Detector to avoid some * very expensive analysis, which is a Big Win for the user. * * @param method the method * @return the BitSet containing the opcodes which appear in the method, * or null if the method has no code */ @CheckForNull public BitSet getBytecodeSet(Method method) { return getBytecodeSet(jclass, method); } /** * Get a BitSet representing the bytecodes that are used in the given method. * This is useful for prescreening a method for the existence of particular instructions. * Because this step doesn't require building a MethodGen, it is very * fast and memory-efficient. It may allow a Detector to avoid some * very expensive analysis, which is a Big Win for the user. * * @param method the method * @return the BitSet containing the opcodes which appear in the method, * or null if the method has no code */ @CheckForNull static public BitSet getBytecodeSet(JavaClass clazz, Method method) { XMethod xmethod = XFactory.createXMethod(clazz, method); if (cachedBitsets.containsKey(xmethod)) { return cachedBitsets.get(xmethod); } Code code = method.getCode(); if (code == null) return null; byte[] instructionList = code.getCode(); // Create callback UnpackedBytecodeCallback callback = new UnpackedBytecodeCallback(instructionList.length); // Scan the method. BytecodeScanner scanner = new BytecodeScanner(); scanner.scan(instructionList, callback); UnpackedCode unpackedCode = callback.getUnpackedCode(); BitSet result = null; if (unpackedCode != null) result = unpackedCode.getBytecodeSet(); cachedBitsets.put(xmethod, result); return result; } @CheckForNull static public Set<Integer> getLoopExitBranches(Method method, MethodGen methodGen) { XMethod xmethod = XFactory.createXMethod(methodGen); if (cachedLoopExits.containsKey(xmethod)) { return cachedLoopExits.get(xmethod); } Code code = method.getCode(); if (code == null) return null; byte[] instructionList = code.getCode(); Set<Integer> result = new HashSet<Integer>(); for(int i = 0; i < instructionList.length; i++) if (checkForBranchExit(instructionList,i)) result.add(i); if (result.size() == 0) result = TigerSubstitutes.emptySet(); // alas, emptySet() is @since 1.5 cachedLoopExits.put(xmethod, result); return result;} static short getBranchOffset(byte [] codeBytes, int pos) { int branchByte1 = 0xff & codeBytes[pos]; int branchByte2 = 0xff & codeBytes[pos+1]; int branchOffset = (short) (branchByte1 << 8 | branchByte2); return (short) branchOffset; } static boolean checkForBranchExit(byte [] codeBytes, int pos) { if (pos < 0 || pos+2 >= codeBytes.length) return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -