Class Subtypes2


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

      • ENABLE_SUBTYPES2_FOR_COMMON_SUPERCLASS_QUERIES

        public static final boolean ENABLE_SUBTYPES2_FOR_COMMON_SUPERCLASS_QUERIES
        See Also:
        Constant Field Values
      • DEBUG

        public static final boolean DEBUG
      • DEBUG_QUERIES

        public static final boolean DEBUG_QUERIES
      • xclassSet

        private final java.util.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
      • prevResult

        boolean prevResult
    • Constructor Detail

      • Subtypes2

        public Subtypes2()
        Constructor.
    • Method Detail

      • isCollection

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

        public static boolean isContainer​(org.apache.bcel.generic.ReferenceType target)
                                   throws java.lang.ClassNotFoundException
        A collection, a map, or some other container
        Throws:
        java.lang.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​(ClassDescriptor subDescriptor,
                                         java.lang.Class<?> c)
      • instanceOf

        public static boolean instanceOf​(org.apache.bcel.classfile.JavaClass subtype,
                                         @DottedClassName
                                         java.lang.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
      • isSubtype

        public boolean isSubtype​(org.apache.bcel.generic.ReferenceType type,
                                 org.apache.bcel.generic.ReferenceType possibleSupertype)
                          throws java.lang.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:
        java.lang.ClassNotFoundException - if a missing class prevents a definitive answer
      • isSubtype

        public boolean isSubtype​(ClassDescriptor subDesc,
                                 ClassDescriptor superDesc)
                          throws java.lang.ClassNotFoundException
        Throws:
        java.lang.ClassNotFoundException
      • isSubtype

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

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

        public boolean isSubtype​(org.apache.bcel.generic.ObjectType type,
                                 org.apache.bcel.generic.ObjectType possibleSupertype)
                          throws java.lang.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:
        java.lang.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 java.lang.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:
        java.lang.ClassNotFoundException
      • computeFirstCommonSuperclassOfReferenceTypes

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

        private org.apache.bcel.generic.ReferenceType computeFirstCommonSuperclassOfSameDimensionArrays​(org.apache.bcel.generic.ArrayType aArrType,
                                                                                                        org.apache.bcel.generic.ArrayType bArrType)
                                                                                                 throws java.lang.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:
        java.lang.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 java.lang.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:
        java.lang.ClassNotFoundException
      • computeFirstCommonSuperclassOfObjectTypes

        private org.apache.bcel.generic.ObjectType computeFirstCommonSuperclassOfObjectTypes​(org.apache.bcel.generic.ObjectType a,
                                                                                             org.apache.bcel.generic.ObjectType b)
                                                                                      throws java.lang.ClassNotFoundException
        Throws:
        java.lang.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 java.util.ArrayList<ClassVertex> getAllSuperclassVertices​(ClassVertex vertex)
                                                                   throws java.lang.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:
        java.lang.ClassNotFoundException
      • getSubtypes

        public java.util.Set<ClassDescriptor> getSubtypes​(ClassDescriptor classDescriptor)
                                                   throws java.lang.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:
        java.lang.ClassNotFoundException
      • hasSubtypes

        public boolean hasSubtypes​(ClassDescriptor classDescriptor)
                            throws java.lang.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:
        java.lang.ClassNotFoundException
      • getDirectSubtypes

        public java.util.Set<ClassDescriptor> getDirectSubtypes​(ClassDescriptor classDescriptor)
                                                         throws java.lang.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:
        java.lang.ClassNotFoundException
      • getTransitiveCommonSubtypes

        public java.util.Set<ClassDescriptor> getTransitiveCommonSubtypes​(ClassDescriptor classDescriptor1,
                                                                          ClassDescriptor classDescriptor2)
                                                                   throws java.lang.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:
        java.lang.ClassNotFoundException
      • getXClassCollection

        public java.util.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 java.lang.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:
        java.lang.ClassNotFoundException - if the start vertex cannot be resolved
      • traverseSupertypesDepthFirst

        public void traverseSupertypesDepthFirst​(ClassDescriptor start,
                                                 SupertypeTraversalVisitor visitor)
                                          throws java.lang.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:
        java.lang.ClassNotFoundException - if the start vertex cannot be resolved
      • computeKnownSubtypes

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

        public boolean hasKnownSubclasses​(ClassDescriptor classDescriptor)
                                   throws java.lang.ClassNotFoundException
        Throws:
        java.lang.ClassNotFoundException
      • computeKnownSupertypes

        private java.util.Set<ClassDescriptor> computeKnownSupertypes​(ClassDescriptor classDescriptor)
                                                               throws java.lang.ClassNotFoundException
        Throws:
        java.lang.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 java.lang.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:
        java.lang.ClassNotFoundException - if the class named by the ClassDescriptor does not exist
      • addSupertypeEdges

        private void addSupertypeEdges​(ClassVertex vertex,
                                       java.util.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
                                        java.util.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