Class Subtypes2

java.lang.Object
edu.umd.cs.findbugs.ba.ch.Subtypes2

@ParametersAreNonnullByDefault public class Subtypes2 extends Object
Class for performing class hierarchy queries. Does not require JavaClass objects to be in memory. Instead, uses XClass objects.
  • Field Details

    • ENABLE_SUBTYPES2_FOR_COMMON_SUPERCLASS_QUERIES

      public static final boolean ENABLE_SUBTYPES2_FOR_COMMON_SUPERCLASS_QUERIES
      See Also:
    • DEBUG

      public static final boolean DEBUG
    • DEBUG_QUERIES

      public static final boolean DEBUG_QUERIES
    • graph

      private final InheritanceGraph graph
    • classDescriptorToVertexMap

      private final Map<ClassDescriptor,ClassVertex> classDescriptorToVertexMap
    • supertypeSetMap

      private final Map<ClassDescriptor,Subtypes2.SupertypeQueryResults> supertypeSetMap
    • subtypeSetMap

      private final Map<ClassDescriptor,Set<ClassDescriptor>> subtypeSetMap
    • xclassSet

      private final Set<XClass> xclassSet
    • firstCommonSuperclassQueryCache

      private final DualKeyHashMap<org.apache.bcel.generic.ReferenceType,org.apache.bcel.generic.ReferenceType,org.apache.bcel.generic.ReferenceType> firstCommonSuperclassQueryCache
    • SERIALIZABLE

      private final org.apache.bcel.generic.ObjectType SERIALIZABLE
    • CLONEABLE

      private final org.apache.bcel.generic.ObjectType CLONEABLE
    • COLLECTION_TYPE

      static final org.apache.bcel.generic.ObjectType COLLECTION_TYPE
    • MAP_TYPE

      static final org.apache.bcel.generic.ObjectType MAP_TYPE
    • prevSubDesc

      ClassDescriptor prevSubDesc
    • prevSuperDesc

      ClassDescriptor prevSuperDesc
    • prevResult

      boolean prevResult
  • Constructor Details

    • Subtypes2

      public Subtypes2()
      Constructor.
  • Method Details

    • getGraph

      public InheritanceGraph getGraph()
      Returns:
      Returns the graph.
    • isCollection

      public static boolean isCollection(org.apache.bcel.generic.ReferenceType target) throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • isContainer

      public static boolean isContainer(org.apache.bcel.generic.ReferenceType target) throws ClassNotFoundException
      A collection, a map, or some other container
      Throws:
      ClassNotFoundException
    • isJSP

      public static boolean isJSP(org.apache.bcel.classfile.JavaClass javaClass)
    • isEnum

      public static boolean isEnum(org.apache.bcel.classfile.JavaClass javaClass)
    • isRecord

      public static boolean isRecord(org.apache.bcel.classfile.JavaClass javaClass)
    • instanceOf

      public static boolean instanceOf(@DottedClassName String dottedSubtype, @DottedClassName String dottedSupertype)
    • instanceOf

      public static boolean instanceOf(ClassDescriptor subDescriptor, Class<?> c)
    • instanceOf

      public static boolean instanceOf(ClassDescriptor subDescriptor, @DottedClassName String dottedSupertype)
    • instanceOf

      public static boolean instanceOf(org.apache.bcel.classfile.JavaClass subtype, @DottedClassName String dottedSupertype)
    • addApplicationClass

      public void addApplicationClass(XClass appXClass)
      Add an application class, and its transitive supertypes, to the inheritance graph.
      Parameters:
      appXClass - application XClass to add to the inheritance graph
    • isApplicationClass

      public boolean isApplicationClass(ClassDescriptor descriptor)
    • addClass

      public void addClass(XClass xclass)
      Add a class or interface, and its transitive supertypes, to the inheritance graph.
      Parameters:
      xclass - XClass to add to the inheritance graph
    • addClassAndGetClassVertex

      private ClassVertex addClassAndGetClassVertex(XClass xclass)
      Add an XClass and all of its supertypes to the InheritanceGraph.
      Parameters:
      xclass - an XClass
      Returns:
      the ClassVertex representing the class in the InheritanceGraph
    • addVertexToGraph

      private void addVertexToGraph(ClassDescriptor classDescriptor, ClassVertex vertex)
    • isSubtype

      public boolean isSubtype(org.apache.bcel.generic.ReferenceType type, org.apache.bcel.generic.ReferenceType possibleSupertype) throws ClassNotFoundException
      Determine whether or not a given ReferenceType is a subtype of another. Throws ClassNotFoundException if the question cannot be answered definitively due to a missing class.
      Parameters:
      type - a ReferenceType
      possibleSupertype - another Reference type
      Returns:
      true if type is a subtype of possibleSupertype, false if not
      Throws:
      ClassNotFoundException - if a missing class prevents a definitive answer
    • isSubtype

      public boolean isSubtype(ClassDescriptor subDesc, ClassDescriptor superDesc) throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • isSubtype

      public boolean isSubtype(ClassDescriptor subDesc, ClassDescriptor... superDesc) throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • isSubtype0

      public boolean isSubtype0(ClassDescriptor subDesc, ClassDescriptor superDesc) throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • isSubtype

      public boolean isSubtype(org.apache.bcel.generic.ObjectType type, org.apache.bcel.generic.ObjectType possibleSupertype) throws ClassNotFoundException
      Determine whether or not a given ObjectType is a subtype of another. Throws ClassNotFoundException if the question cannot be answered definitively due to a missing class.
      Parameters:
      type - a ReferenceType
      possibleSupertype - another Reference type
      Returns:
      true if type is a subtype of possibleSupertype, false if not
      Throws:
      ClassNotFoundException - if a missing class prevents a definitive answer
    • getFirstCommonSuperclass

      public org.apache.bcel.generic.ReferenceType getFirstCommonSuperclass(org.apache.bcel.generic.ReferenceType a, org.apache.bcel.generic.ReferenceType b) throws ClassNotFoundException
      Get the first common superclass of the given reference types. Note that an interface type is never returned unless a and b are the same type. Otherwise, we try to return as accurate a type as possible. This method is used as the meet operator in TypeDataflowAnalysis, and is intended to follow (more or less) the JVM bytecode verifier semantics.

      This method should be used in preference to the getFirstCommonSuperclass() method in ReferenceType.

      Parameters:
      a - a ReferenceType
      b - another ReferenceType
      Returns:
      the first common superclass of a and b
      Throws:
      ClassNotFoundException
    • computeFirstCommonSuperclassOfReferenceTypes

      private org.apache.bcel.generic.ReferenceType computeFirstCommonSuperclassOfReferenceTypes(org.apache.bcel.generic.ReferenceType a, org.apache.bcel.generic.ReferenceType b) throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • computeFirstCommonSuperclassOfSameDimensionArrays

      private org.apache.bcel.generic.ReferenceType computeFirstCommonSuperclassOfSameDimensionArrays(org.apache.bcel.generic.ArrayType aArrType, org.apache.bcel.generic.ArrayType bArrType) throws ClassNotFoundException
      Get first common supertype of arrays with the same number of dimensions.
      Parameters:
      aArrType - an ArrayType
      bArrType - another ArrayType with the same number of dimensions
      Returns:
      first common supertype
      Throws:
      ClassNotFoundException
    • computeFirstCommonSuperclassOfDifferentDimensionArrays

      private org.apache.bcel.generic.ReferenceType computeFirstCommonSuperclassOfDifferentDimensionArrays(org.apache.bcel.generic.ArrayType aArrType, org.apache.bcel.generic.ArrayType bArrType)
      Get the first common superclass of arrays with different numbers of dimensions.
      Parameters:
      aArrType - an ArrayType
      bArrType - another ArrayType
      Returns:
      ReferenceType representing first common superclass
    • getFirstCommonSuperclass

      public org.apache.bcel.generic.ObjectType getFirstCommonSuperclass(org.apache.bcel.generic.ObjectType a, org.apache.bcel.generic.ObjectType b) throws ClassNotFoundException
      Get the first common superclass of the given object types. Note that an interface type is never returned unless a and b are the same type. Otherwise, we try to return as accurate a type as possible. This method is used as the meet operator in TypeDataflowAnalysis, and is intended to follow (more or less) the JVM bytecode verifier semantics.

      This method should be used in preference to the getFirstCommonSuperclass() method in ReferenceType.

      Parameters:
      a - an ObjectType
      b - another ObjectType
      Returns:
      the first common superclass of a and b
      Throws:
      ClassNotFoundException
    • computeFirstCommonSuperclassOfObjectTypes

      private org.apache.bcel.generic.ObjectType computeFirstCommonSuperclassOfObjectTypes(org.apache.bcel.generic.ObjectType a, org.apache.bcel.generic.ObjectType b) throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • putFirstCommonSuperclassQueryCache

      private void putFirstCommonSuperclassQueryCache(org.apache.bcel.generic.ReferenceType a, org.apache.bcel.generic.ReferenceType b, org.apache.bcel.generic.ReferenceType answer)
    • checkFirstCommonSuperclassQueryCache

      private org.apache.bcel.generic.ReferenceType checkFirstCommonSuperclassQueryCache(org.apache.bcel.generic.ReferenceType a, org.apache.bcel.generic.ReferenceType b)
    • getAllSuperclassVertices

      private ArrayList<ClassVertex> getAllSuperclassVertices(ClassVertex vertex) throws ClassNotFoundException
      Get list of all superclasses of class represented by given class vertex, in order, including the class itself (which is trivially its own superclass as far as "first common superclass" queries are concerned.)
      Parameters:
      vertex - a ClassVertex
      Returns:
      list of all superclass vertices in order
      Throws:
      ClassNotFoundException
    • getSubtypes

      public Set<ClassDescriptor> getSubtypes(ClassDescriptor classDescriptor) throws ClassNotFoundException
      Get known subtypes of given class. The set returned DOES include the class itself.
      Parameters:
      classDescriptor - ClassDescriptor naming a class
      Returns:
      Set of ClassDescriptors which are the known subtypes of the class
      Throws:
      ClassNotFoundException
    • hasSubtypes

      public boolean hasSubtypes(ClassDescriptor classDescriptor) throws ClassNotFoundException
      Determine whether or not the given class has any known subtypes.
      Parameters:
      classDescriptor - ClassDescriptor naming a class
      Returns:
      true if the class has subtypes, false if it has no subtypes
      Throws:
      ClassNotFoundException
    • getDirectSubtypes

      public Set<ClassDescriptor> getDirectSubtypes(ClassDescriptor classDescriptor) throws ClassNotFoundException
      Get known subtypes of given class.
      Parameters:
      classDescriptor - ClassDescriptor naming a class
      Returns:
      Set of ClassDescriptors which are the known subtypes of the class
      Throws:
      ClassNotFoundException
    • getTransitiveCommonSubtypes

      public Set<ClassDescriptor> getTransitiveCommonSubtypes(ClassDescriptor classDescriptor1, ClassDescriptor classDescriptor2) throws ClassNotFoundException
      Get the set of common subtypes of the two given classes.
      Parameters:
      classDescriptor1 - a ClassDescriptor naming a class
      classDescriptor2 - a ClassDescriptor naming another class
      Returns:
      Set containing all common transitive subtypes of the two classes
      Throws:
      ClassNotFoundException
    • getXClassCollection

      public Collection<XClass> getXClassCollection()
      Get Collection of all XClass objects (resolved classes) seen so far.
      Returns:
      Collection of all XClass objects
    • traverseSupertypes

      public void traverseSupertypes(ClassDescriptor start, InheritanceGraphVisitor visitor) throws ClassNotFoundException
      Starting at the class or interface named by the given ClassDescriptor, traverse the inheritance graph, exploring all paths from the class or interface to java.lang.Object.
      Parameters:
      start - ClassDescriptor naming the class where the traversal should start
      visitor - an InheritanceGraphVisitor
      Throws:
      ClassNotFoundException - if the start vertex cannot be resolved
    • traverseSupertypesDepthFirst

      public void traverseSupertypesDepthFirst(ClassDescriptor start, SupertypeTraversalVisitor visitor) throws ClassNotFoundException
      Starting at the class or interface named by the given ClassDescriptor, traverse the inheritance graph depth first, visiting each class only once. This is much faster than traversing all paths in certain circumstances.
      Parameters:
      start - ClassDescriptor naming the class where the traversal should start
      visitor - an InheritanceGraphVisitor
      Throws:
      ClassNotFoundException - if the start vertex cannot be resolved
    • traverseSupertypesDepthFirstHelper

      private void traverseSupertypesDepthFirstHelper(ClassDescriptor cur, SupertypeTraversalVisitor visitor, Set<ClassDescriptor> seen) throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • addToWorkList

      private void addToWorkList(LinkedList<Subtypes2.SupertypeTraversalPath> workList, Subtypes2.SupertypeTraversalPath curPath, ClassDescriptor supertypeDescriptor)
    • traverseEdge

      private boolean traverseEdge(ClassVertex vertex, @CheckForNull ClassDescriptor supertypeDescriptor, boolean isInterfaceEdge, InheritanceGraphVisitor visitor)
    • computeKnownSubtypes

      private Set<ClassDescriptor> computeKnownSubtypes(ClassDescriptor classDescriptor) throws ClassNotFoundException
      Compute set of known subtypes of class named by given ClassDescriptor.
      Parameters:
      classDescriptor - a ClassDescriptor
      Throws:
      ClassNotFoundException
    • hasKnownSubclasses

      public boolean hasKnownSubclasses(ClassDescriptor classDescriptor) throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • computeKnownSupertypes

      private Set<ClassDescriptor> computeKnownSupertypes(ClassDescriptor classDescriptor) throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • getSupertypeQueryResults

      public Subtypes2.SupertypeQueryResults getSupertypeQueryResults(ClassDescriptor classDescriptor)
      Look up or compute the SupertypeQueryResults for class named by given ClassDescriptor.
      Parameters:
      classDescriptor - a ClassDescriptor
      Returns:
      SupertypeQueryResults for the class named by the ClassDescriptor
    • computeSupertypes

      private Subtypes2.SupertypeQueryResults computeSupertypes(ClassDescriptor classDescriptor)
      Compute supertypes for class named by given ClassDescriptor.
      Parameters:
      classDescriptor - a ClassDescriptor
      Returns:
      SupertypeQueryResults containing known supertypes of the class
    • resolveClassVertex

      private ClassVertex resolveClassVertex(ClassDescriptor classDescriptor) throws ClassNotFoundException
      Resolve a class named by given ClassDescriptor and return its resolved ClassVertex.
      Parameters:
      classDescriptor - a ClassDescriptor
      Returns:
      resolved ClassVertex representing the class in the InheritanceGraph
      Throws:
      ClassNotFoundException - if the class named by the ClassDescriptor does not exist
    • optionallyResolveClassVertex

      private ClassVertex optionallyResolveClassVertex(ClassDescriptor classDescriptor)
    • addSupertypeEdges

      private void addSupertypeEdges(ClassVertex vertex, LinkedList<XClass> workList)
      Add supertype edges to the InheritanceGraph for given ClassVertex. If any direct supertypes have not been processed, add them to the worklist.
      Parameters:
      vertex - a ClassVertex whose supertype edges need to be added
      workList - work list of ClassVertexes that need to have their supertype edges added
    • addInheritanceEdge

      private void addInheritanceEdge(ClassVertex vertex, ClassDescriptor superclassDescriptor, boolean isInterfaceEdge, @CheckForNull LinkedList<XClass> workList)
      Add supertype edge to the InheritanceGraph.
      Parameters:
      vertex - source ClassVertex (subtype)
      superclassDescriptor - ClassDescriptor of a direct supertype
      isInterfaceEdge - true if supertype is (as far as we know) an interface
      workList - work list of ClassVertexes that need to have their supertype edges added (null if no further work will be generated)
    • addClassVertexForMissingClass

      private ClassVertex addClassVertexForMissingClass(ClassDescriptor missingClassDescriptor, boolean isInterfaceEdge)
      Add a ClassVertex representing a missing class.
      Parameters:
      missingClassDescriptor - ClassDescriptor naming a missing class
      isInterfaceEdge -
      Returns:
      the ClassVertex representing the missing class