📄 classcontext.java
字号:
public CFG getRefinedCFG(Method method) throws CFGBuilderException { CFG cfg = getRawCFG(method); if (cfg.isFlagSet(REFINED)) return cfg; MethodGen methodGen = getMethodGen(method); if (methodGen == null) { JavaClassAndMethod javaClassAndMethod = new JavaClassAndMethod(jclass, method); getLookupFailureCallback().reportSkippedAnalysis(javaClassAndMethod.toMethodDescriptor()); throw new MethodUnprofitableException(javaClassAndMethod); } // Record method name and signature for informational purposes cfg.setMethodName(SignatureConverter.convertMethodSignature(methodGen)); cfg.setMethodGen(methodGen); // HACK: // Due to recursive method invocations, we may get a recursive // request for the pruned CFG of a method. In this case, // we just return the raw CFG. String methodId = methodGen.getClassName() + "." + methodGen.getName() + ":" + methodGen.getSignature(); // System.out.println("CC: getting refined CFG for " + methodId); if (DEBUG_CFG) { indent(); System.out.println("CC: getting refined CFG for " + methodId); } if (DEBUG) System.out.println("ClassContext: request to prune " + methodId); if (!busyCFGSet.add(methodId)) return cfg; cfg.setFlags(REFINED); boolean changed = false; boolean ASSUME_ASSERTIONS_ENABLED = true; if (ASSUME_ASSERTIONS_ENABLED) { LinkedList<Edge> edgesToRemove = new LinkedList<Edge>(); for (Iterator<Edge> i = cfg.edgeIterator(); i.hasNext();) { Edge e = i.next(); if (e.getType() == EdgeTypes.IFCMP_EDGE) { try { BasicBlock source = e.getSource(); InstructionHandle last = source .getLastInstruction(); Instruction lastInstruction = last.getInstruction(); InstructionHandle prev = last.getPrev(); Instruction prevInstruction = prev.getInstruction(); if (prevInstruction instanceof GETSTATIC && lastInstruction instanceof IFNE) { GETSTATIC getStatic = (GETSTATIC) prevInstruction; if (false) { System.out.println(prev); System.out.println(getStatic .getClassName(methodGen .getConstantPool())); System.out.println(getStatic .getFieldName(methodGen .getConstantPool())); System.out.println(getStatic .getSignature(methodGen .getConstantPool())); System.out.println(last); } if (getStatic.getFieldName( methodGen.getConstantPool()).equals( "$assertionsDisabled") && getStatic.getSignature( methodGen.getConstantPool()) .equals("Z")) edgesToRemove.add(e); } } catch (RuntimeException exception) { assert true; // ignore it } } } for (Edge e : edgesToRemove) { cfg.removeEdge(e); } } final boolean PRUNE_INFEASIBLE_EXCEPTION_EDGES = analysisContext.getBoolProperty(AnalysisFeatures.ACCURATE_EXCEPTIONS); if (PRUNE_INFEASIBLE_EXCEPTION_EDGES && !cfg.isFlagSet(PRUNED_INFEASIBLE_EXCEPTIONS)) { try { TypeDataflow typeDataflow = getTypeDataflow(method); // Exception edge pruning based on ExceptionSets. // Note: this is quite slow. PruneInfeasibleExceptionEdges pruner = new PruneInfeasibleExceptionEdges(cfg, methodGen, typeDataflow); pruner.execute(); changed = changed || pruner.wasCFGModified(); } catch (DataflowAnalysisException e) { // FIXME: should report the error } catch (ClassNotFoundException e) { getLookupFailureCallback().reportMissingClass(e); } } cfg.setFlags(cfg.getFlags() | PRUNED_INFEASIBLE_EXCEPTIONS); final boolean PRUNE_UNCONDITIONAL_EXCEPTION_THROWER_EDGES = !analysisContext.getBoolProperty(AnalysisFeatures.CONSERVE_SPACE); if (PRUNE_UNCONDITIONAL_EXCEPTION_THROWER_EDGES && !cfg.isFlagSet(PRUNED_UNCONDITIONAL_THROWERS)) { try { PruneUnconditionalExceptionThrowerEdges pruner = new PruneUnconditionalExceptionThrowerEdges(ClassContext.this, jclass, method, methodGen, cfg, getConstantPoolGen(), analysisContext); pruner.execute(); changed = changed || pruner.wasCFGModified(); } catch (DataflowAnalysisException e) { // FIXME: should report the error } } cfg.setFlags(cfg.getFlags() | PRUNED_UNCONDITIONAL_THROWERS); if (changed) { ClassContext.this.purgeAnalysisResultsAfterCFGPruning(method); } busyCFGSet.remove(methodId); return cfg; } @Override protected CFG analyze(Method method) throws CFGBuilderException { MethodGen methodGen = getMethodGen(method); if (methodGen == null) { JavaClassAndMethod javaClassAndMethod = new JavaClassAndMethod(jclass, method); getLookupFailureCallback().reportSkippedAnalysis(javaClassAndMethod.toMethodDescriptor()); throw new MethodUnprofitableException(javaClassAndMethod); } CFGBuilder cfgBuilder = CFGBuilderFactory.create(methodGen); cfgBuilder.build(); return cfgBuilder.getCFG(); } /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.ClassContext.AnalysisFactory#isDataflow() */ @Override public boolean isDataflow() { return false; } } private abstract class DataflowAnalysisFactory<Analysis> extends AnalysisFactory<Analysis> { DataflowAnalysisFactory(String desc) { super(desc); } /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.ClassContext.AnalysisFactory#isDataflow() */ @Override public boolean isDataflow() { return true; } } /* ---------------------------------------------------------------------- * Fields * ---------------------------------------------------------------------- */ private JavaClass jclass; private AnalysisContext analysisContext; // List of all analysis factories. private List<AnalysisFactory<?>> analysisFactoryList = new LinkedList<AnalysisFactory<?>>(); private NoExceptionAnalysisFactory<MethodGen> methodGenFactory = new NoExceptionAnalysisFactory<MethodGen>("MethodGen construction") { @CheckForNull @Override protected MethodGen analyze(Method method) { if (method.getCode() == null) return null; try { String methodName = method.getName(); if (analysisContext.getBoolProperty(AnalysisFeatures.SKIP_HUGE_METHODS)) { int codeLength = method.getCode().getLength(); if (codeLength > 3000 || (methodName.equals("<clinit>") || methodName.equals("getContents")) && codeLength > 1000) { getLookupFailureCallback().reportSkippedAnalysis(new JavaClassAndMethod(jclass, method).toMethodDescriptor()); return null; } } return new MethodGen(method, jclass.getClassName(), getConstantPoolGen()); } catch (Exception e) { AnalysisContext.logError("Error constructing methodGen", e); return null; } } }; private CFGFactory cfgFactory = new CFGFactory(); private AnalysisFactory<UsagesRequiringNonNullValues> derefFactory = new AnalysisFactory<UsagesRequiringNonNullValues>("Dereference factory") { @Override protected UsagesRequiringNonNullValues analyze(Method method) throws CFGBuilderException, DataflowAnalysisException { return DerefFinder.getAnalysis(ClassContext.this, method); } @Override public boolean isDataflow() { return false; } }; private AnalysisFactory<ValueNumberDataflow> vnaDataflowFactory = new DataflowAnalysisFactory<ValueNumberDataflow>("value number analysis") { @Override protected ValueNumberDataflow analyze(Method method) throws DataflowAnalysisException, CFGBuilderException { MethodGen methodGen = getMethodGen(method); if (methodGen == null) throw new MethodUnprofitableException(getJavaClass(),method); DepthFirstSearch dfs = getDepthFirstSearch(method); LoadedFieldSet loadedFieldSet = getLoadedFieldSet(method); ValueNumberAnalysis analysis = new ValueNumberAnalysis(methodGen, dfs, loadedFieldSet, getLookupFailureCallback()); analysis.setMergeTree(new MergeTree(analysis.getFactory())); CFG cfg = getCFG(method); ValueNumberDataflow vnaDataflow = new ValueNumberDataflow(cfg, analysis); vnaDataflow.execute(); if (DUMP_DATAFLOW_ANALYSIS) { TreeSet<Location> tree = new TreeSet<Location>(); for(Iterator<Location> locs = cfg.locationIterator(); locs.hasNext(); ) { Location loc = locs.next(); tree.add(loc); } System.out.println("\n\nValue number analysis for " + method.getName() + " {"); for(Location loc : tree) { System.out.println("\nBefore: " + vnaDataflow.getFactAtLocation(loc)); System.out.println("Location: " + loc); System.out.println("After: " + vnaDataflow.getFactAfterLocation(loc)); } System.out.println("}\n"); } return vnaDataflow; } }; private AnalysisFactory<IsNullValueDataflow> invDataflowFactory = new DataflowAnalysisFactory<IsNullValueDataflow>("null value analysis") { @Override protected IsNullValueDataflow analyze(Method method) throws DataflowAnalysisException, CFGBuilderException { MethodGen methodGen = getMethodGen(method); if (methodGen == null) throw new MethodUnprofitableException(getJavaClass(),method); CFG cfg = getCFG(method); ValueNumberDataflow vnaDataflow = getValueNumberDataflow(method); DepthFirstSearch dfs = getDepthFirstSearch(method); AssertionMethods assertionMethods = getAssertionMethods(); IsNullValueAnalysis invAnalysis = new IsNullValueAnalysis(methodGen, cfg, vnaDataflow, dfs, assertionMethods); // Set return value and parameter databases invAnalysis.setClassAndMethod(new JavaClassAndMethod(getJavaClass(), method)); IsNullValueDataflow invDataflow = new IsNullValueDataflow(cfg, invAnalysis); invDataflow.execute(); if (DUMP_DATAFLOW_ANALYSIS) { TreeSet<Location> tree = new TreeSet<Location>(); for(Iterator<Location> locs = cfg.locationIterator(); locs.hasNext(); ) { Location loc = locs.next(); tree.add(loc); } System.out.println("\n\nInv analysis for " + method.getName() + " {"); for(Location loc : tree) { System.out.println("\nBefore: " + invDataflow.getFactAtLocation(loc)); System.out.println("Location: " + loc); System.out.println("After: " + invDataflow.getFactAfterLocation(loc)); } System.out.println("}\n"); } return invDataflow; } }; private AnalysisFactory<TypeDataflow> typeDataflowFactory = new DataflowAnalysisFactory<TypeDataflow>("type analysis") { @Override protected TypeDataflow analyze(Method method) throws DataflowAnalysisException, CFGBuilderException { MethodGen methodGen = getMethodGen(method); if (methodGen == null) throw new MethodUnprofitableException(getJavaClass(),method); CFG cfg = getRawCFG(method); DepthFirstSearch dfs = getDepthFirstSearch(method); ExceptionSetFactory exceptionSetFactory = getExceptionSetFactory(method); TypeAnalysis typeAnalysis = new TypeAnalysis(method, methodGen, cfg, dfs, getLookupFailureCallback(), exceptionSetFactory); if (analysisContext.getBoolProperty(AnalysisFeatures.MODEL_INSTANCEOF)) { typeAnalysis.setValueNumberDataflow(getValueNumberDataflow(method)); } // Field store type database. // If present, this can give us more accurate type information // for values loaded from fields. typeAnalysis.setFieldStoreTypeDatabase(analysisContext.getFieldStoreTypeDatabase()); TypeDataflow typeDataflow = new TypeDataflow(cfg, typeAnalysis); typeDataflow.execute(); if (TypeAnalysis.DEBUG) { dumpTypeDataflow(method, cfg, typeDataflow); } return typeDataflow; } }; private NoDataflowAnalysisFactory<DepthFirstSearch> dfsFactory = new NoDataflowAnalysisFactory<DepthFirstSearch>("depth first search") { @Override protected DepthFirstSearch analyze(Method method) throws CFGBuilderException { CFG cfg = getRawCFG(method); DepthFirstSearch dfs = new DepthFirstSearch(cfg); dfs.search(); return dfs; } }; private NoDataflowAnalysisFactory<ReverseDepthFirstSearch> rdfsFactory = new NoDataflowAnalysisFactory<ReverseDepthFirstSearch>("reverse depth first search") { @Override protected ReverseDepthFirstSearch analyze(Method method) throws CFGBuilderException { CFG cfg = getRawCFG(method); ReverseDepthFirstSearch rdfs = new ReverseDepthFirstSearch(cfg); rdfs.search(); return rdfs; } }; private static class UnpackedBytecodeCallback implements BytecodeScanner.Callback { private BitSet bytecodeSet; private short[] offsetToOpcodeMap; public UnpackedBytecodeCallback(int codeSize) { this.bytecodeSet = new BitSet(); this.offsetToOpcodeMap = new short[codeSize]; } /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.BytecodeScanner.Callback#handleInstruction(int, int) */ public void handleInstruction(int opcode, int index) { bytecodeSet.set(opcode); offsetToOpcodeMap[index] = (short) opcode; } public UnpackedCode getUnpackedCode() { return new UnpackedCode(bytecodeSet, offsetToOpcodeMap); } } private NoExceptionAnalysisFactory<UnpackedCode> unpackedCodeFactory = new NoExceptionAnalysisFactory<UnpackedCode>("unpacked bytecode") { @Override protected UnpackedCode analyze(Method method) { Code code = method.getCode(); if (code == null) return null; byte[] instructionList = code.getCode();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -