📄 finddeadlocalstores.java
字号:
javaClass.getSourceFileName(), location.getHandle()); complainedAbout.set(local); } if (storeLive) continue; TypeFrame typeFrame = typeDataflow.getAnalysis().getFactAtLocation(location); Type typeOfValue = null; if (typeFrame.isValid() && typeFrame.getStackDepth() > 0) { typeOfValue = TypeFrame.getTopType(); } boolean storeOfNull = false; InstructionHandle prevInsHandle = location.getHandle().getPrev(); if (prevInsHandle != null) { Instruction prevIns = prevInsHandle.getInstruction(); if (prevIns instanceof LDC || prevIns instanceof ConstantPushInstruction) propertySet.addProperty(DeadLocalStoreProperty.STORE_OF_CONSTANT); else if (prevIns instanceof ACONST_NULL) { storeOfNull = true; propertySet.addProperty(DeadLocalStoreProperty.STORE_OF_NULL); } } for (Field f : javaClass.getFields()) { if (f.getName().equals(name)) { propertySet.addProperty(DeadLocalStoreProperty.SHADOWS_FIELD); break; } } if (typeOfValue instanceof BasicType || Type.STRING.equals(typeOfValue)) propertySet.addProperty(DeadLocalStoreProperty.BASE_VALUE); // Ignore assignments that were killed by a subsequent // assignment. boolean killedBySubsequentStore = llsaDataflow.getAnalysis().killedByStore(liveStoreSet, local); if (killedBySubsequentStore) propertySet.addProperty(DeadLocalStoreProperty.KILLED_BY_SUBSEQUENT_STORE); // Ignore dead assignments of null and 0. // These often indicate defensive programming. InstructionHandle prev = location.getBasicBlock().getPredecessorOf(location.getHandle()); int prevOpCode = -1; if (prev != null) { if (defensiveConstantValueOpcodes.get(prev.getInstruction().getOpcode())) { propertySet.addProperty(DeadLocalStoreProperty.DEFENSIVE_CONSTANT_OPCODE); prevOpCode = prev.getInstruction().getOpcode(); } if (prev.getInstruction() instanceof GETFIELD) { InstructionHandle prev2 = prev.getPrev(); if (prev2 != null && prev2.getInstruction() instanceof ALOAD) propertySet.addProperty(DeadLocalStoreProperty.CACHING_VALUE); } if (prev.getInstruction() instanceof LoadInstruction) propertySet.addProperty(DeadLocalStoreProperty.COPY_VALUE); if (prev.getInstruction() instanceof InvokeInstruction) propertySet.addProperty(DeadLocalStoreProperty.METHOD_RESULT); } boolean deadObjectStore = false; if (ins instanceof IINC) { // special handling of IINC propertySet.addProperty(DeadLocalStoreProperty.DEAD_INCREMENT); if (localIncrementCount[local] == 1) { propertySet.addProperty(DeadLocalStoreProperty.SINGLE_DEAD_INCREMENT); } else propertySet.removeProperty(DeadLocalStoreProperty.IS_PARAMETER); } else if (ins instanceof ASTORE && prev != null) { // Look for objects created but never used Instruction prevIns = prev.getInstruction(); if ((prevIns instanceof INVOKESPECIAL && ((INVOKESPECIAL) prevIns).getMethodName(methodGen.getConstantPool()) .equals("<init>")) || prevIns instanceof ANEWARRAY || prevIns instanceof NEWARRAY || prevIns instanceof MULTIANEWARRAY) { deadObjectStore = true; } } if (deadObjectStore) propertySet.addProperty(DeadLocalStoreProperty.DEAD_OBJECT_STORE); else if (!killedBySubsequentStore && localStoreCount[local] == 2 && localLoadCount[local] > 0) { // TODO: why is this significant? propertySet.addProperty(DeadLocalStoreProperty.TWO_STORES_MULTIPLE_LOADS); } else if (!parameterThatIsDeadAtEntry && localStoreCount[local] == 1 && localLoadCount[local] == 0 && propertySet.containsProperty(DeadLocalStoreProperty.DEFENSIVE_CONSTANT_OPCODE)) { // might be final local constant propertySet.addProperty(DeadLocalStoreProperty.SINGLE_STORE); } else if (!parameterThatIsDeadAtEntry && !propertySet.containsProperty(DeadLocalStoreProperty.SHADOWS_FIELD) && localLoadCount[local] == 0) { // TODO: why is this significant? propertySet.addProperty(DeadLocalStoreProperty.NO_LOADS); } if (parameterThatIsDeadAtEntry) { propertySet.addProperty(DeadLocalStoreProperty.PARAM_DEAD_ON_ENTRY); if (pendingBugReportAboutOverwrittenParameter != null) pendingBugReportAboutOverwrittenParameter.setPriority(Detector.HIGH_PRIORITY); } if (localStoreCount[local] > 3) propertySet.addProperty(DeadLocalStoreProperty.MANY_STORES); int priority = propertySet.computePriority(NORMAL_PRIORITY); if (priority <= Detector.EXP_PRIORITY) { // Report the warning BugInstance bugInstance = new BugInstance(this, storeOfNull ? "DLS_DEAD_LOCAL_STORE_OF_NULL" : "DLS_DEAD_LOCAL_STORE", priority).addClassAndMethod( methodGen, javaClass.getSourceFileName()).add(lvAnnotation); // If in relaxed reporting mode, encode heuristic // information. if (FindBugsAnalysisFeatures.isRelaxedMode()) { // Add general-purpose warning properties WarningPropertyUtil.addPropertiesForLocation(propertySet, classContext, method, location); // Turn all warning properties into BugProperties propertySet.decorateBugInstance(bugInstance); } if (DEBUG) { System.out.println(javaClass.getSourceFileName() + " : " + methodGen.getName()); System.out.println("priority: " + priority); System.out.println("Reporting " + bugInstance); System.out.println(propertySet); } accumulator.accumulateBug(bugInstance, sourceLineAnnotation); } } finally { if (pendingBugReportAboutOverwrittenParameter != null) bugReporter.reportBug(pendingBugReportAboutOverwrittenParameter); } } suppressWarningsIfOneLiveStoreOnLine(accumulator, liveStoreSourceLineSet); accumulator.reportAccumulatedBugs(); } /** * If feature is enabled, suppress warnings where there is at least * one live store on the line where the warning would be reported. * * @param accumulator BugAccumulator containing warnings for method * @param liveStoreSourceLineSet bitset of lines where at least one live store was seen */ private void suppressWarningsIfOneLiveStoreOnLine(BugAccumulator accumulator, BitSet liveStoreSourceLineSet) { if (!SUPPRESS_IF_AT_LEAST_ONE_LIVE_STORE_ON_LINE) { return; } // Eliminate any accumulated warnings for instructions // that (due to inlining) *can* be live stores. entryLoop: for (Iterator<Map.Entry<BugInstance, List<SourceLineAnnotation>>> i = accumulator.entrySetIterator(); i.hasNext(); ) { Map.Entry<BugInstance, List<SourceLineAnnotation>> entry = i.next(); for (SourceLineAnnotation annotation : entry.getValue()) { if (liveStoreSourceLineSet.get(annotation.getStartLine())) { // This instruction can be a live store; don't report // it as a warning. i.remove(); continue entryLoop; } } } } /** * Count stores, loads, and increments of local variables in method whose * CFG is given. * * @param localStoreCount * counts of local stores (indexed by local) * @param localLoadCount * counts of local loads (indexed by local) * @param localIncrementCount * counts of local increments (indexed by local) * @param cfg * control flow graph (CFG) of method */ private void countLocalStoresLoadsAndIncrements(int[] localStoreCount, int[] localLoadCount, int[] localIncrementCount, CFG cfg) { for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) { Location location = i.next(); if (location.getBasicBlock().isExceptionHandler()) continue; boolean isStore = isStore(location); boolean isLoad = isLoad(location); if (!isStore && !isLoad) continue; IndexedInstruction ins = (IndexedInstruction) location.getHandle().getInstruction(); int local = ins.getIndex(); if (ins instanceof IINC) { localStoreCount[local]++; localLoadCount[local]++; localIncrementCount[local]++; } else if (isStore) localStoreCount[local]++; else localLoadCount[local]++; } } /** * Get the name of given local variable (if possible) and store it in the * HeuristicPropertySet. * * @param lvt * the LocalVariableTable * @param local * index of the local * @param pc * program counter value of the instruction */ private void checkLocalVariableName(LocalVariableTable lvt, int local, int pc, WarningPropertySet propertySet) { if (lvt != null) { LocalVariable lv = lvt.getLocalVariable(local, pc); if (lv != null) { String localName = lv.getName(); propertySet.setProperty(DeadLocalStoreProperty.LOCAL_NAME, localName); } } } /** * Is instruction at given location a store? * * @param location * the location * @return true if instruction at given location is a store, false if not */ private boolean isStore(Location location) { Instruction ins = location.getHandle().getInstruction(); return (ins instanceof StoreInstruction) || (ins instanceof IINC); } /** * Is instruction at given location a load? * * @param location * the location * @return true if instruction at given location is a load, false if not */ private boolean isLoad(Location location) { Instruction ins = location.getHandle().getInstruction(); return (ins instanceof LoadInstruction) || (ins instanceof IINC); } public void report() { }}//vim:ts=4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -