Class BloatedAssignmentScope

  • 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 BloatedAssignmentScope
    extends edu.umd.cs.findbugs.BytecodeScanningDetector
    looks for variable assignments at a scope larger than its use. In this case, the assignment can be pushed down into the smaller scope to reduce the performance impact of that assignment.
    • Nested Class Summary

      Nested Classes 
      Modifier and Type Class Description
      private class  BloatedAssignmentScope.ScopeBlock
      holds the description of a scope { } block, be it a for, if, while block
      (package private) static class  BloatedAssignmentScope.UserObject
      represents the source of an assignment to a variable, which could be a method call or a field
    • Field Summary

      Fields 
      Modifier and Type Field Description
      (package private) edu.umd.cs.findbugs.BugReporter bugReporter  
      private java.util.BitSet catchHandlers  
      private static java.util.Set<java.lang.String> dangerousAssignmentClassSources  
      private static java.util.Set<java.util.regex.Pattern> dangerousAssignmentMethodPatterns  
      private static java.util.Set<FQMethod> dangerousAssignmentMethodSources  
      private static java.util.Set<java.lang.String> dangerousStoreClassSigs  
      private boolean dontReport  
      private java.util.BitSet ignoreRegs  
      private java.util.List<java.lang.Integer> monitorSyncPCs  
      private BloatedAssignmentScope.ScopeBlock rootScopeBlock  
      private boolean sawDup  
      private boolean sawNull  
      private edu.umd.cs.findbugs.OpcodeStack stack  
      private java.util.BitSet switchTargets  
      private java.util.BitSet tryBlocks  
      • 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
      BloatedAssignmentScope​(edu.umd.cs.findbugs.BugReporter bugReporter)
      constructs a BAS detector given the reporter to report bugs on
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      private int findCatchHandlerFor​(int pc)
      returns the catch handler for a given try block
      private BloatedAssignmentScope.ScopeBlock findPreviousSiblingScopeBlock​(BloatedAssignmentScope.ScopeBlock sb)
      looks for the ScopeBlock has the same parent as this given one, but precedes it in the list.
      private BloatedAssignmentScope.ScopeBlock findScopeBlock​(BloatedAssignmentScope.ScopeBlock sb, int pc)
      returns the scope block in which this register was assigned, by traversing the scope block tree
      private BloatedAssignmentScope.ScopeBlock findScopeBlockWithTarget​(BloatedAssignmentScope.ScopeBlock sb, int start, int target)
      returns an existing scope block that has the same target as the one looked for
      private BloatedAssignmentScope.ScopeBlock findSynchronizedScopeBlock​(BloatedAssignmentScope.ScopeBlock sb, int monitorEnterPC)
      finds the scope block that is the active synchronized block
      private java.lang.Comparable<?> getCallingObject()
      returns either a register number of a field reference of the object that a method is being called on, or null, if it can't be determined.
      boolean isRiskyMethodCall()  
      boolean isRiskyStoreClass​(int reg)  
      private void sawBranch​(int seen, int pc)
      creates a scope block to describe this branch location.
      private BloatedAssignmentScope.UserObject sawGetField()  
      private void sawIINC​(int pc)
      processes a register IINC by updating the appropriate scope block to mark this register as being stored in the block
      private BloatedAssignmentScope.UserObject sawInstanceCall​(int pc)
      processes a instance method call to see if that call is modifies state or is otherwise'risky', if so mark the variable(s) associated with the caller as not reportable
      private void sawLoad​(int seen, int pc)
      processes a register store by updating the appropriate scope block to mark this register as being read in the block
      private void sawMonitorEnter​(int pc)
      processes a monitor enter call to create a scope block
      private void sawMonitorExit​(int pc)
      processes a monitor exit to set the end of the already created scope block
      void sawOpcode​(int seen)
      implements the visitor to look for variables assigned below the scope in which they are used.
      private void sawPutField​(int pc)  
      private BloatedAssignmentScope.UserObject sawStaticCall()
      processes a static call or initializer by checking to see if the call is risky, and returning a OpcodeStack item user value saying so.
      private void sawStore​(int seen, int pc)
      processes a register store by updating the appropriate scope block to mark this register as being stored in the block
      private void sawSwitch​(int pc)
      creates a new scope block for each case statement
      void visitClassContext​(edu.umd.cs.findbugs.ba.ClassContext classContext)
      implements the visitor to create and the clear the register to location map
      void visitCode​(org.apache.bcel.classfile.Code obj)
      implements the visitor to reset the register to location map
      • 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

      • dangerousAssignmentClassSources

        private static final java.util.Set<java.lang.String> dangerousAssignmentClassSources
      • dangerousAssignmentMethodSources

        private static final java.util.Set<FQMethod> dangerousAssignmentMethodSources
      • dangerousAssignmentMethodPatterns

        private static final java.util.Set<java.util.regex.Pattern> dangerousAssignmentMethodPatterns
      • dangerousStoreClassSigs

        private static final java.util.Set<java.lang.String> dangerousStoreClassSigs
      • bugReporter

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

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

        private java.util.BitSet ignoreRegs
      • tryBlocks

        private java.util.BitSet tryBlocks
      • catchHandlers

        private java.util.BitSet catchHandlers
      • switchTargets

        private java.util.BitSet switchTargets
      • monitorSyncPCs

        private java.util.List<java.lang.Integer> monitorSyncPCs
      • dontReport

        private boolean dontReport
      • sawDup

        private boolean sawDup
      • sawNull

        private boolean sawNull
    • Constructor Detail

      • BloatedAssignmentScope

        public BloatedAssignmentScope​(edu.umd.cs.findbugs.BugReporter bugReporter)
        constructs a BAS 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 the clear the register to location map
        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 parsed class
      • visitCode

        public void visitCode​(org.apache.bcel.classfile.Code obj)
        implements the visitor to reset the register to location map
        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 variables assigned below the scope in which they are used.
        Overrides:
        sawOpcode in class edu.umd.cs.findbugs.visitclass.DismantleBytecode
        Parameters:
        seen - the opcode of the currently parsed instruction
      • sawStore

        private void sawStore​(int seen,
                              int pc)
        processes a register store by updating the appropriate scope block to mark this register as being stored in the block
        Parameters:
        seen - the currently parsed opcode
        pc - the current program counter
      • sawIINC

        private void sawIINC​(int pc)
        processes a register IINC by updating the appropriate scope block to mark this register as being stored in the block
        Parameters:
        pc - the current program counter
      • sawLoad

        private void sawLoad​(int seen,
                             int pc)
        processes a register store by updating the appropriate scope block to mark this register as being read in the block
        Parameters:
        seen - the currently parsed opcode
        pc - the current program counter
      • sawBranch

        private void sawBranch​(int seen,
                               int pc)
        creates a scope block to describe this branch location.
        Parameters:
        seen - the currently parsed opcode
        pc - the current program counter
      • sawSwitch

        private void sawSwitch​(int pc)
        creates a new scope block for each case statement
        Parameters:
        pc - the current program counter
      • sawInstanceCall

        @Nullable
        private BloatedAssignmentScope.UserObject sawInstanceCall​(int pc)
        processes a instance method call to see if that call is modifies state or is otherwise'risky', if so mark the variable(s) associated with the caller as not reportable
        Parameters:
        pc - the current program counter
        Returns:
        a user object to place on the return value's OpcodeStack item
      • sawStaticCall

        @Nullable
        private BloatedAssignmentScope.UserObject sawStaticCall()
        processes a static call or initializer by checking to see if the call is risky, and returning a OpcodeStack item user value saying so.
        Returns:
        the user object to place on the OpcodeStack
      • sawPutField

        private void sawPutField​(int pc)
      • sawMonitorEnter

        private void sawMonitorEnter​(int pc)
        processes a monitor enter call to create a scope block
        Parameters:
        pc - the current program counter
      • sawMonitorExit

        private void sawMonitorExit​(int pc)
        processes a monitor exit to set the end of the already created scope block
        Parameters:
        pc - the current program counter
      • getCallingObject

        @Nullable
        private java.lang.Comparable<?> getCallingObject()
        returns either a register number of a field reference of the object that a method is being called on, or null, if it can't be determined.
        Returns:
        either an Integer for a register, or a String for the field name, or null
      • findScopeBlock

        @Nullable
        private BloatedAssignmentScope.ScopeBlock findScopeBlock​(BloatedAssignmentScope.ScopeBlock sb,
                                                                 int pc)
        returns the scope block in which this register was assigned, by traversing the scope block tree
        Parameters:
        sb - the scope block to start searching in
        pc - the current program counter
        Returns:
        the scope block or null if not found
      • findScopeBlockWithTarget

        private BloatedAssignmentScope.ScopeBlock findScopeBlockWithTarget​(BloatedAssignmentScope.ScopeBlock sb,
                                                                           int start,
                                                                           int target)
        returns an existing scope block that has the same target as the one looked for
        Parameters:
        sb - the scope block to start with
        start - the current pc
        target - the target to look for
        Returns:
        the scope block found or null
      • findPreviousSiblingScopeBlock

        @Nullable
        private BloatedAssignmentScope.ScopeBlock findPreviousSiblingScopeBlock​(BloatedAssignmentScope.ScopeBlock sb)
        looks for the ScopeBlock has the same parent as this given one, but precedes it in the list.
        Parameters:
        sb - the scope block to look for the previous scope block
        Returns:
        the previous sibling scope block, or null if doesn't exist
      • findSynchronizedScopeBlock

        private BloatedAssignmentScope.ScopeBlock findSynchronizedScopeBlock​(BloatedAssignmentScope.ScopeBlock sb,
                                                                             int monitorEnterPC)
        finds the scope block that is the active synchronized block
        Parameters:
        sb - the parent scope block to start with
        monitorEnterPC - the pc where the current synchronized block starts
        Returns:
        the scope block
      • findCatchHandlerFor

        private int findCatchHandlerFor​(int pc)
        returns the catch handler for a given try block
        Parameters:
        pc - the current instruction
        Returns:
        the pc of the handler for this pc if it's the start of a try block, or -1
      • isRiskyMethodCall

        public boolean isRiskyMethodCall()
      • isRiskyStoreClass

        public boolean isRiskyStoreClass​(int reg)