Class PossiblyRedundantMethodCalls

  • All Implemented Interfaces:
    edu.umd.cs.findbugs.Detector, edu.umd.cs.findbugs.Priorities, edu.umd.cs.findbugs.visitclass.Constants2, org.apache.bcel.classfile.Visitor, org.apache.bcel.Constants

    @CustomUserValue
    public class PossiblyRedundantMethodCalls
    extends edu.umd.cs.findbugs.BytecodeScanningDetector
    looks for calls of the same method on the same object when that object hasn't changed. This often is redundant, and the second call can be removed, or combined.
    • Field Summary

      Fields 
      Modifier and Type Field Description
      private java.util.BitSet branchTargets  
      private edu.umd.cs.findbugs.BugReporter bugReporter  
      private static java.util.Set<FQMethod> commonMethods  
      private java.util.Map<PossiblyRedundantMethodCalls.FieldInfo,​PossiblyRedundantMethodCalls.MethodCall> fieldMethodCalls  
      private static int highByteCountLimit  
      private static int highMethodCallLimit  
      private java.util.Map<java.lang.Integer,​PossiblyRedundantMethodCalls.MethodCall> localMethodCalls  
      private static int lowByteCountLimit  
      private static int lowMethodCallLimit  
      private static int normalByteCountLimit  
      private static int normalMethodCallLimit  
      static java.lang.String PRMC_HIGH_BYTECOUNT  
      static java.lang.String PRMC_HIGH_METHODCALLS  
      static java.lang.String PRMC_LOW_BYTECOUNT  
      static java.lang.String PRMC_LOW_METHODCALLS  
      static java.lang.String PRMC_NORMAL_BYTECOUNT  
      static java.lang.String PRMC_NORMAL_METHODCALLS  
      static java.lang.String PRMC_RISKY_CLASS_USER_KEY  
      static java.lang.String PRMC_RISKY_FIELD_USER_KEY  
      private static java.util.Set<java.lang.String> riskyClassNames  
      private static java.util.Set<java.lang.String> riskyMethodNameContents
      a collection of names that are to be checked against a currently parsed method, to see if that method is risky to be called redundant.
      private edu.umd.cs.findbugs.OpcodeStack stack  
      private java.util.Map<java.lang.String,​PossiblyRedundantMethodCalls.MethodCall> staticMethodCalls  
      • Fields inherited from class edu.umd.cs.findbugs.visitclass.DismantleBytecode

        codeBytes, lineNumberTable, M_BR, M_CP, M_INT, M_PAD, M_R, M_UINT
      • Fields inherited from interface org.apache.bcel.Constants

        AALOAD, AASTORE, ACC_ABSTRACT, ACC_ANNOTATION, ACC_BRIDGE, ACC_ENUM, ACC_FINAL, ACC_INTERFACE, ACC_NATIVE, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_STATIC, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_SYNTHETIC, ACC_SYPER, ACC_TRANSIENT, ACC_VARARGS, ACC_VOLATILE, ACCESS_NAMES, ACONST_NULL, ALOAD, ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3, ANEWARRAY, ANEWARRAY_QUICK, APPEND_FRAME, APPEND_FRAME_MAX, ARETURN, ARRAYLENGTH, ASTORE, ASTORE_0, ASTORE_1, ASTORE_2, ASTORE_3, ATHROW, ATTR_ANNOTATION_DEFAULT, ATTR_CODE, ATTR_CONSTANT_VALUE, ATTR_DEPRECATED, ATTR_ENCLOSING_METHOD, ATTR_EXCEPTIONS, ATTR_INNER_CLASSES, ATTR_LINE_NUMBER_TABLE, ATTR_LOCAL_VARIABLE_TABLE, ATTR_LOCAL_VARIABLE_TYPE_TABLE, ATTR_PMG, ATTR_RUNTIME_VISIBLE_ANNOTATIONS, ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS, ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS, ATTR_SIGNATURE, ATTR_SOURCE_FILE, ATTR_STACK_MAP, ATTR_STACK_MAP_TABLE, ATTR_SYNTHETIC, ATTR_UNKNOWN, ATTRIBUTE_NAMES, BALOAD, BASTORE, BIPUSH, BREAKPOINT, CALOAD, CASTORE, CHECKCAST, CHECKCAST_QUICK, CHOP_FRAME, CHOP_FRAME_MAX, CLASS_TYPE_NAMES, CONSTANT_Class, CONSTANT_Double, CONSTANT_Fieldref, CONSTANT_Float, CONSTANT_Integer, CONSTANT_InterfaceMethodref, CONSTANT_InvokeDynamic, CONSTANT_Long, CONSTANT_MethodHandle, CONSTANT_Methodref, CONSTANT_MethodType, CONSTANT_NameAndType, CONSTANT_NAMES, CONSTANT_String, CONSTANT_Utf8, CONSTRUCTOR_NAME, CONSUME_STACK, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3, DMUL, DNEG, DREM, DRETURN, DSTORE, DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FLOAD_0, FLOAD_1, FLOAD_2, FLOAD_3, FMUL, FNEG, FREM, FRETURN, FSTORE, FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3, FSUB, FULL_FRAME, GETFIELD, GETFIELD_QUICK, GETFIELD_QUICK_W, GETFIELD2_QUICK, GETSTATIC, GETSTATIC_QUICK, GETSTATIC2_QUICK, GOTO, GOTO_W, I2B, I2C, I2D, I2F, I2L, I2S, IADD, IALOAD, IAND, IASTORE, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, ICONST_M1, IDIV, IF_ACMPEQ, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, IFNONNULL, IFNULL, IINC, ILLEGAL_OPCODE, ILLEGAL_TYPE, ILOAD, ILOAD_0, ILOAD_1, ILOAD_2, ILOAD_3, IMPDEP1, IMPDEP2, IMUL, INEG, INSTANCEOF, INSTANCEOF_QUICK, INT2BYTE, INT2CHAR, INT2SHORT, INTERFACES_IMPLEMENTED_BY_ARRAYS, INVOKEDYNAMIC, INVOKEINTERFACE, INVOKEINTERFACE_QUICK, INVOKENONVIRTUAL, INVOKENONVIRTUAL_QUICK, INVOKESPECIAL, INVOKESTATIC, INVOKESTATIC_QUICK, INVOKESUPER_QUICK, INVOKEVIRTUAL, INVOKEVIRTUAL_QUICK, INVOKEVIRTUAL_QUICK_W, INVOKEVIRTUALOBJECT_QUICK, IOR, IREM, IRETURN, ISHL, ISHR, ISTORE, ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3, ISUB, ITEM_Bogus, ITEM_Double, ITEM_Float, ITEM_InitObject, ITEM_Integer, ITEM_Long, ITEM_NAMES, ITEM_NewObject, ITEM_Null, ITEM_Object, IUSHR, IXOR, JSR, JSR_W, KNOWN_ATTRIBUTES, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, LCONST_0, LCONST_1, LDC, LDC_QUICK, LDC_W, LDC_W_QUICK, LDC2_W, LDC2_W_QUICK, LDIV, LLOAD, LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3, LMUL, LNEG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3, LSUB, LUSHR, LXOR, MAJOR, MAJOR_1_1, MAJOR_1_2, MAJOR_1_3, MAJOR_1_4, MAJOR_1_5, MAJOR_1_6, MAJOR_1_7, MAJOR_1_8, MAX_ACC_FLAG, MAX_BYTE, MAX_CODE_SIZE, MAX_CP_ENTRIES, MAX_SHORT, MINOR, MINOR_1_1, MINOR_1_2, MINOR_1_3, MINOR_1_4, MINOR_1_5, MINOR_1_6, MINOR_1_7, MINOR_1_8, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, MULTIANEWARRAY_QUICK, NEW, NEW_QUICK, NEWARRAY, NO_OF_OPERANDS, NOP, OPCODE_NAMES, POP, POP2, PRODUCE_STACK, PUSH, PUTFIELD, PUTFIELD_QUICK, PUTFIELD_QUICK_W, PUTFIELD2_QUICK, PUTSTATIC, PUTSTATIC_QUICK, PUTSTATIC2_QUICK, RESERVED, RET, RETURN, SALOAD, SAME_FRAME, SAME_FRAME_EXTENDED, SAME_FRAME_MAX, SAME_LOCALS_1_STACK_ITEM_FRAME, SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED, SAME_LOCALS_1_STACK_ITEM_FRAME_MAX, SASTORE, SHORT_TYPE_NAMES, SIPUSH, STATIC_INITIALIZER_NAME, SWAP, SWITCH, T_ADDRESS, T_ARRAY, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_OBJECT, T_REFERENCE, T_SHORT, T_UNKNOWN, T_VOID, TABLESWITCH, TYPE_NAMES, TYPE_OF_OPERANDS, UNDEFINED, UNPREDICTABLE, WIDE
      • Fields inherited from interface edu.umd.cs.findbugs.Priorities

        EXP_PRIORITY, HIGH_PRIORITY, IGNORE_PRIORITY, LOW_PRIORITY, NORMAL_PRIORITY
    • Constructor Summary

      Constructors 
      Constructor Description
      PossiblyRedundantMethodCalls​(edu.umd.cs.findbugs.BugReporter bugReporter)
      constructs a PRMC detector given the reporter to report bugs on
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      private void clearFieldMethods​(java.lang.String fieldSource)  
      private static int getBugPriority​(java.lang.String methodName, MethodInfo mi)
      returns the bug priority based on metrics about the method
      private int getLineNumber​(int pc)
      returns the source line number for the pc, or just the pc if the line number table doesn't exist
      private static boolean isRiskyName​(java.lang.String className, java.lang.String methodName)
      returns true if the class or method name contains a pattern that is considered likely to be this modifying
      void sawOpcode​(int seen)
      implements the visitor to look for repetitive calls to the same method on the same object using the same constant parameters.
      void visitClassContext​(edu.umd.cs.findbugs.ba.ClassContext classContext)
      implements the visitor to create and clear the stack, method call maps, and branch targets
      void visitCode​(org.apache.bcel.classfile.Code obj)
      implements the visitor to reset the stack, and method call maps for new method Note: that when collecting branch targets, it's unfortunately not good enough to just collect the handler pcs, as javac plays fast and loose, and will sometimes jam code below the end pc and before the first handler pc, which gets executed.
      • Methods inherited from class edu.umd.cs.findbugs.BytecodeScanningDetector

        getClassContext, report, shouldVisitCode
      • Methods inherited from class edu.umd.cs.findbugs.visitclass.DismantleBytecode

        afterOpcode, areOppositeBranches, atCatchBlock, beforeOpcode, getBranchFallThrough, getBranchOffset, getBranchTarget, getClassConstantOperand, getClassDescriptorOperand, getCodeByte, getConstantRefOperand, getDefaultSwitchOffset, getDottedClassConstantOperand, getFieldDescriptorOperand, getIntConstant, getLongConstant, getMaxPC, getMethodDescriptorOperand, getNameConstantOperand, getNextCodeByte, getNextOpcode, getNextPC, getOpcode, getPC, getPrevOpcode, getRefConstantOperand, getRefFieldIsStatic, getRegisterOperand, getSigConstantOperand, getStringConstantOperand, getSwitchLabels, getSwitchOffsets, getXClassOperand, getXFieldOperand, getXMethodOperand, isBranch, isMethodCall, isRegisterLoad, isRegisterStore, isRegisterStore, isReturn, isShift, isSwitch, isWideOpcode, printOpCode, sawBranchTo, sawClass, sawDouble, sawField, sawFloat, sawIMethod, sawInt, sawLong, sawMethod, sawRegister, sawString, visit
      • Methods inherited from class edu.umd.cs.findbugs.visitclass.AnnotationVisitor

        getAnnotationParameterAsString, getAnnotationParameterAsStringArray, visitAnnotation, visitAnnotation, visitParameterAnnotation, visitParameterAnnotation, visitSyntheticParameterAnnotation
      • Methods inherited from class edu.umd.cs.findbugs.visitclass.PreorderVisitor

        amVisitingMainMethod, asUnsignedByte, doVisitMethod, getClassDescriptor, getClassName, getCode, getConstantPool, getDottedClassName, getDottedFieldSig, getDottedMethodSig, getDottedSuperclassName, getField, getFieldDescriptor, getFieldIsStatic, getFieldName, getFieldSig, getFullyQualifiedFieldName, getFullyQualifiedMethodName, getMethod, getMethodDescriptor, getMethodName, getMethodSig, getMethodVisitOrder, getNumberArguments, getNumberMethodArguments, getPackageName, getSizeOfSurroundingTryBlock, getSizeOfSurroundingTryBlock, getSourceFile, getStringFromIndex, getSuperclassName, getSurroundingCaughtExceptions, getSurroundingCaughtExceptions, getSurroundingTryBlock, getSurroundingTryBlock, getThisClass, getXClass, getXField, getXMethod, hasInterestingClass, hasInterestingMethod, isVisitMethodsInCallOrder, setupVisitorForClass, setVisitMethodsInCallOrder, shouldVisit, toString, visitAfter, visitAfter, visitAnnotationDefault, visitAnnotationEntry, visitConstantPool, visitEnclosingMethod, visitingField, visitingMethod, visitInnerClasses, visitJavaClass, visitLineNumberTable, visitLocalVariableTable, visitStackMapTable, visitStackMapTableEntry
      • Methods inherited from class edu.umd.cs.findbugs.visitclass.BetterVisitor

        clone, report, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visit, visitCodeException, visitConstantClass, visitConstantDouble, visitConstantFieldref, visitConstantFloat, visitConstantInteger, visitConstantInterfaceMethodref, visitConstantLong, visitConstantMethodref, visitConstantNameAndType, visitConstantString, visitConstantUtf8, visitConstantValue, visitDeprecated, visitExceptionTable, visitField, visitInnerClass, visitLineNumber, visitLocalVariable, visitLocalVariableTypeTable, visitMethod, visitSignature, visitSourceFile, visitStackMap, visitStackMapEntry, visitSynthetic, visitUnknown
      • Methods inherited from class java.lang.Object

        equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
    • Field Detail

      • PRMC_RISKY_FIELD_USER_KEY

        public static final java.lang.String PRMC_RISKY_FIELD_USER_KEY
        See Also:
        Constant Field Values
      • PRMC_RISKY_CLASS_USER_KEY

        public static final java.lang.String PRMC_RISKY_CLASS_USER_KEY
        See Also:
        Constant Field Values
      • PRMC_HIGH_BYTECOUNT

        public static final java.lang.String PRMC_HIGH_BYTECOUNT
        See Also:
        Constant Field Values
      • PRMC_HIGH_METHODCALLS

        public static final java.lang.String PRMC_HIGH_METHODCALLS
        See Also:
        Constant Field Values
      • PRMC_NORMAL_BYTECOUNT

        public static final java.lang.String PRMC_NORMAL_BYTECOUNT
        See Also:
        Constant Field Values
      • PRMC_NORMAL_METHODCALLS

        public static final java.lang.String PRMC_NORMAL_METHODCALLS
        See Also:
        Constant Field Values
      • PRMC_LOW_BYTECOUNT

        public static final java.lang.String PRMC_LOW_BYTECOUNT
        See Also:
        Constant Field Values
      • PRMC_LOW_METHODCALLS

        public static final java.lang.String PRMC_LOW_METHODCALLS
        See Also:
        Constant Field Values
      • riskyMethodNameContents

        private static java.util.Set<java.lang.String> riskyMethodNameContents
        a collection of names that are to be checked against a currently parsed method, to see if that method is risky to be called redundant. The contents are either
        • a simple name that can be found as part of the methodName, like "destroy" which would match destroy(), or destroyAll()
        • a fully qualified method name that exactly matches a method, like "java/lang/String.valueOf"
      • highByteCountLimit

        private static int highByteCountLimit
      • highMethodCallLimit

        private static int highMethodCallLimit
      • normalByteCountLimit

        private static int normalByteCountLimit
      • normalMethodCallLimit

        private static int normalMethodCallLimit
      • lowByteCountLimit

        private static int lowByteCountLimit
      • lowMethodCallLimit

        private static int lowMethodCallLimit
      • riskyClassNames

        private static java.util.Set<java.lang.String> riskyClassNames
      • commonMethods

        private static final java.util.Set<FQMethod> commonMethods
      • bugReporter

        private final edu.umd.cs.findbugs.BugReporter bugReporter
      • stack

        private edu.umd.cs.findbugs.OpcodeStack stack
      • branchTargets

        private java.util.BitSet branchTargets
    • Constructor Detail

      • PossiblyRedundantMethodCalls

        public PossiblyRedundantMethodCalls​(edu.umd.cs.findbugs.BugReporter bugReporter)
        constructs a PRMC detector given the reporter to report bugs on
        Parameters:
        bugReporter - the sync of bug reports
    • Method Detail

      • visitClassContext

        public void visitClassContext​(edu.umd.cs.findbugs.ba.ClassContext classContext)
        implements the visitor to create and clear the stack, method call maps, and branch targets
        Specified by:
        visitClassContext in interface edu.umd.cs.findbugs.Detector
        Overrides:
        visitClassContext in class edu.umd.cs.findbugs.BytecodeScanningDetector
        Parameters:
        classContext - the context object of the currently visited class
      • visitCode

        public void visitCode​(org.apache.bcel.classfile.Code obj)
        implements the visitor to reset the stack, and method call maps for new method Note: that when collecting branch targets, it's unfortunately not good enough to just collect the handler pcs, as javac plays fast and loose, and will sometimes jam code below the end pc and before the first handler pc, which gets executed. So we need to clear our maps if we go past the end pc as well.
        Specified by:
        visitCode in interface org.apache.bcel.classfile.Visitor
        Overrides:
        visitCode in class edu.umd.cs.findbugs.visitclass.PreorderVisitor
        Parameters:
        obj - the context object of the currently parsed code block
      • sawOpcode

        public void sawOpcode​(int seen)
        implements the visitor to look for repetitive calls to the same method on the same object using the same constant parameters. These methods must return a value.
        Overrides:
        sawOpcode in class edu.umd.cs.findbugs.visitclass.DismantleBytecode
        Parameters:
        seen - the opcode of the currently parsed instruction
      • clearFieldMethods

        private void clearFieldMethods​(java.lang.String fieldSource)
      • getBugPriority

        private static int getBugPriority​(java.lang.String methodName,
                                          MethodInfo mi)
        returns the bug priority based on metrics about the method
        Parameters:
        methodName - TODO
        mi - metrics about the method
        Returns:
        the bug priority
      • isRiskyName

        private static boolean isRiskyName​(java.lang.String className,
                                           java.lang.String methodName)
        returns true if the class or method name contains a pattern that is considered likely to be this modifying
        Parameters:
        className - the class name to check
        methodName - the method name to check
        Returns:
        whether the method sounds like it modifies this
      • getLineNumber

        private int getLineNumber​(int pc)
        returns the source line number for the pc, or just the pc if the line number table doesn't exist
        Parameters:
        pc - current pc
        Returns:
        the line number