Returns all (direct and indirect) subclasses of the given class type.
The set of all class- and interface-types that (directly or indirectly) inherit from the given type.
The set of all class- and interface-types that (directly or indirectly) inherit from the given type.
A known ObjectType
. (See ClassHierarchy.isKnown
,
ClassHierarchy.ifKnown
for further details).
If true
the given type is also included in the returned
set.
The set of all direct and indirect subtypes of the given type.
If the type hierarchy is not complete the answer may not be correct. E.g., if x inherits from y and y inherits from z, but y is not known to the class hierarchy then x will not be in the set of all (known) subtypes of z.
,If you don't need the set, it is more efficient to use foreachSubtype
.
Returns the set of all interfaces directly or indirectly implemented by the given type.
Returns the set of all interfaces directly or indirectly implemented by the given type.
If true
the returned set will also contain the given type if
it is an interface type.
The set of all supertypes of the given type.
The set of all supertypes of the given type.
If true
the returned set will also contain the given type.
Calculates the set of all supertypes of the given types
.
Determines if a value of type elementValueType
can be stored in an array of
type arrayType
.
Determines if a value of type elementValueType
can be stored in an array of
type arrayType
. E.g. a value of type IntegerType
can be stored in an
array (one-dimensional) of type ArrayType(IntegerType)
. This method takes
the fact that a type may just model an upper type bound into account.
The type of the value that should be stored in the array. This type is compared against the component type of the array.
Specifies if the type information is precise;
i.e., whether elementValueType models the precise runtime type (true
)
or just an upper bound (false
). If the elementValueType
is a base/
primitive type then this value should be true
; but actually it is
ignored.
The type of the array.
Specifies if the type information is precise;
i.e., whether arrayType models the precise runtime type (true
)
or just an upper bound (false
).
A set of types that are in no inheritance relationship.
The direct subtypes of the given type.
Tests if a subtype of the given ObjectType
exists that has the given property.
Tests if a subtype of the given ObjectType
exists that has the given property.
In this case the subtype relation is not reflexive.
Subtypes for which no ClassFile
object is available are ignored.
Executes the given function f
for each known direct subclass of the given ObjectType
.
Executes the given function f
for each known direct subclass of the given ObjectType
.
In this case the subclass relation is not reflexive and interfaces inheriting from
the given object type are ignored.
Subtypes for which no ClassFile
object is available are ignored.
Calls the given function f
for each type that is known to the class hierarchy.
Executes the given function f
for each subclass of the given ObjectType
.
Executes the given function f
for each subclass of the given ObjectType
.
In this case the subclass relation is not reflexive. Furthermore, it may be
possible the f is invoked multiple times using the same ClassFile
object.
Subtypes for which no ClassFile
object is available are ignored.
For details regarding incomplete class hierarchies see foreachSubtype.
Calls the function f
for each known (direct or indirect) subtype of the given type.
Calls the function f
for each known (direct or indirect) subtype of the given type.
If the given objectType
identifies an interface type then it is possible
that f
is passed the same ObjectType
multiple times.
For details regarding incomplete class hierarchies see allSubtypes.
Calls the function f
for each supertype of the given object type for
which the classfile is available.
Calls the function f
for each supertype of the given object type for
which the classfile is available.
It is possible that the class file of the same super interface type I
is passed multiple times to f
when I
is implemented multiple times
by the given type's supertypes.
The algorithm first iterates over the type's super classes before it iterates over the super interfaces.
See foreachSupertype for details.
Calls the given function f
for each of the given type's supertypes.
Calls the given function f
for each of the given type's supertypes.
It is possible that the same super interface type I
is passed multiple
times to f
when I
is implemented multiple times by the given type's supertypes.
Returns the ObjectType
with the given Id.
Returns the ObjectType
with the given Id. The id has to be the id of a valid
ObjectType.
Determines whether the given ClassSignature of the potential subtype
does implement or extend
the given type supertype
of type ObjectType.
Determines whether the given ClassSignature of the potential subtype
does implement or extend
the given type supertype
of type ObjectType.
In case that the subtype
does implement or extend the supertype
, an Option
of
ClassTypeSignature is returned. Otherwise None will be returned.
Any type or interface.
Any type or interface.
Option
of ClassTypeSignature if the subtype
extends or implements
the given supertype
, None
otherwise.
subtype: ClassSignature from class A where A extends List<String> supertype: List as ObjectType This method scans all super classes and super interfaces of A in order to find the concrete class declaration of List where it is bound to String. The above example would yield the ClassTypeSignature of List<String>.
Retuns Yes
if the class hierarchy contains subtypes of the given type and No
if
it contains no subtypes.
Retuns Yes
if the class hierarchy contains subtypes of the given type and No
if
it contains no subtypes. Unknown
is returned if the given type is not known.
Please note, that the answer maybe No
even though the (running) project will
contain (in)direct subtypes of the given type.
For example, this will be the case if the class hierarchy is not
complete, because not all class files (libraries) used by the project that is
analyzed are also analyzed. A second case is that some class files are generated
at runtime that inherit from the given ObjectType
.
Some ObjectType
.
Tests if the given objectType is known and if so executes the given function.
Tests if the given objectType is known and if so executes the given function.
ifKnown(ObjectType.Serializable){isDirectSupertypeInformationComplete}
Returns true
if the type hierarchy information related to the given type's
supertypes is complete.
Returns true
if the type hierarchy information related to the given type's
supertypes is complete.
Returns true
if the given objectType
defines an interface type.
Returns true
if the class hierarchy has some information about the given
type.
Returns true
if the class hierarchy has some information about the given
type.
Returns true
if the given type is final
.
Returns true
if the given type is final
. I.e., the declaring class
was explicitly declared final or – if the type identifies an array type –
the component type is either known to be final or is a primitive/base type.
false
is returned if:
Returns true
if the given type is final
.
Returns true
if the given type is final
. I.e., the declaring class
was explicitly declared final
and no subtypes exist.
false
is returned if:
Determines if the given class or interface type encoded in a ClassTypeSignature
subtype
is actually a subtype of the class, interface or intersection type encoded
in the FormalTypeParameter of the supertype
parameter.
Determines if the given class or interface type encoded in a ClassTypeSignature
subtype
is actually a subtype of the class, interface or intersection type encoded
in the FormalTypeParameter of the supertype
parameter. The subtype relation is
fulfilled if the subtype is a subtype of the class bound and/or all interface types
that are prescribed by the formal type specification.
Any ClassTypeSignature
.
Any FormalTypeParameter
.
Yes
if subtype
is a subtype of the given supertype
. No
if subtype
is not a subtype of supertype
and Unknown
if the analysis is
not conclusive. The latter can happen if the class hierarchy is not
complete and hence precise information about a type's supertypes
is not available.
This method does consider generics types specified within the FormalTypeParameter.
Determines if the given class or interface type encoded by the
ClassTypeSignature subtype
is actually a subtype
of the class or interface type encoded in the ClassTypeSignature of the
supertype
.
Determines if the given class or interface type encoded by the
ClassTypeSignature subtype
is actually a subtype
of the class or interface type encoded in the ClassTypeSignature of the
supertype
.
Any ClassTypeSignature
.
Any ClassTypeSignature
.
Yes
if subtype
is a subtype of the given supertype
. No
if subtype
is not a subtype of supertype
and Unknown
if the analysis is
not conclusive. The latter can happen if the class hierarchy is not
complete and hence precise information about a type's supertypes
is not available.
subtype: Foo<Integer, String> // Foo<T,E> extends Bar<E>
supertype: Bar<String> // Bar<E>
Does the subtype
and supertype
have FormalTypeParameters and the ContainerType of the subtype
is a subtype of the ContainerType of the supertype
, we have to compare the shared TypeArguments. In
our example the subtype Foo has two FormalTypeParameter (T,E) and the supertype Bar has only one
FormalTypeParameter (E). Since both of them specify E in the ClassSignature of Foo, they share E as
FormalTypeParameter. So it is necessary to check whether the acctual bound TypeArgument at the
postion of E is equal. At first we have to locate the shared parameter in the ClassSignature, so it is possible
to find the correct TypeArguments. The above example shows that the shared parameter E is in the second postion
of the FormalTypeParameters of Foo and at the first postion of the FormalTypeParameters of Bar. Second and last
we know can compare the according TypeArguments. All other parameters can be ignored because they are no important
to decide the subtype relation.
subtype: SomeClass // SomeClass extends SomeInterface<String>
supertype: SomeInterface<String> // SomeInterface<E>
Is the subtype
a ConcreteType without org.opalj.br.FormalTypeParameters and the supertype
is a GenericType then
we first have to check whether the subtype
is a subtype of the given supertype
. If not, then the subtype
is not an actual
subtype of the given supertype
. Otherwise we have to find the definition of the supertype
in the type defintion
or the type definiton of a super class or a super interface (interface definiton of SomeInterface<String>).
Once found the supertype
, we can compare all TypeArguments of the supertype defintion of the subtype
and the given supertype
. (We are comparing String and String in this example)
If all of them are equal, subtype
is an actual subtype of the supertype
.
instance // definition
subtype: List<String> // List<E>
supertype: List<String> // List<E>
If the ContainerType of the subtype
is equal to the ContainerType of the supertype
and non of the
TypeArguments has a VarianceIndicator, then exists a subtype relation if and only if all of the
TypeArguments are equal.
Before looking in some examples, we have to set up the terminology.
Type definition: List<String, ? extends Number, ?>
ContainerType - A ContainerType is a type with parameters. In the previous type definition
is List
the ContainerType.
TypeArgument - A TypeArgument is one of the parameters of the ContainerType. The above type
definition has three TypeArguments. (String, ? extends Number and ?)
VarianceIndicator - A VarianceIndicator is defined in the context of TypeArguments. There
is a CovariantIndicator which can be defined in the type definition by using the
extends
keyword. (? extends Number is a covariant TypeArgument). The other
one is the ContravariantIndicator which is defined using the super
keyword.
This method relies – in case of a comparison of non generic types – on
isSubtypeOf(org.opalj.br.ObjectType,org.opalj.br.ObjectType)
of Project
which
performs an upwards search only. E.g., given the following
type hierarchy:
class D inherits from C
class E inherits from D
and the query isSubtypeOf(D,E) the answer will be Unknown
if C
is
Unknown
and No
otherwise.
Determines if the type described by the first set of upper type bounds is a subtype of the second type.
Determines if the type described by the first set of upper type bounds is a subtype of the second type. I.e., it checks if for all types of the subtypes upper type bound a type in the supertypes type exists that is a supertype of the respective subtype.
Determines if subtype
is a subtype of supertype
using this
class hierarchy.
Determines if subtype
is a subtype of supertype
using this
class hierarchy.
This method can be used as a foundation for implementing the logic of the JVM's
instanceof
and classcast
instructions. But, in both cases additional logic
for handling null
values and for considering the runtime type needs to be
implemented by the caller of this method.
Any class, interface or array type.
Any class, interface or array type.
Yes
if subtype
is indeed a subtype of the given supertype
. No
if subtype
is not a subtype of supertype
and Unknown
if the analysis is
not conclusive. The latter can happen if the class hierarchy is not
completely available and hence precise information about a type's supertypes
is not available.
The answer No
does not necessarily imply that two runtime values for
which the given types are only upper bounds are not (w.r.t. their
runtime types) in a subtype relation. E.g., if subtype
denotes the type
java.util.List
and supertype
denotes the type java.util.ArrayList
then
the answer is clearly No
. But, at runtime, this may not be the case. I.e.,
only the answer Yes
is conclusive. In case of No
further information
needs to be taken into account by the caller to determine what it means that
the (upper) type (bounds) of the underlying values are not in an inheritance
relation.
Determines if the given class or interface type subtype
is actually a subtype
of the class or interface type supertype
.
Determines if the given class or interface type subtype
is actually a subtype
of the class or interface type supertype
.
This method can be used as a foundation for implementing the logic of the JVM's
instanceof
and checkcast
instructions. But, in that case additional logic
for handling null
values and for considering the runtime type needs to be
implemented by the caller of this method.
Any ObjectType
.
Any ObjectType
.
Yes
if subtype
is a subtype of the given supertype
. No
if subtype
is not a subtype of supertype
and Unknown
if the analysis is
not conclusive. The latter can happen if the class hierarchy is not
complete and hence precise information about a type's supertypes
is not available.
This method performs an upwards search only. E.g., given the following
type hierarchy:
class D inherits from C
class E inherits from D
and the query isSubtypeOf(D,E) the answer will be Unknown
if C
is
Unknown
and No
otherwise.
Returns true
if the type is unknown.
Returns true
if the type is unknown. This is true
for all types that are
referred to in the body of a method, but which are not referred to in the
declarations of the class files that were analyzed.
Calculates the most specific common supertype of any array type and some class-/interface type.
Calculates the most specific common supertype of any array type and some class-/interface type.
Recall that (Java) arrays implement Cloneable
and Serializable
.
Calculates the most specific common supertype of any array type and some class-/interface type.
Calculates the most specific common supertype of any array type and some class-/interface type.
Recall that (Java) arrays implement Cloneable
and Serializable
.
Calculates the most specific common supertype of two array types.
Calculates the most specific common supertype of two array types.
Left(<SOME_ARRAYTYPE>)
if the calculated type can be represented using
an ArrayType
and Right(UIDList(ObjectType.Serializable, ObjectType.Cloneable))
if the two arrays do not have an ArrayType
as a most specific common supertype.
Tries to calculate the most specific common supertype of the two given types.
Tries to calculate the most specific common supertype of the two given types.
If reflexive
is false
, the two types do not have to be in an inheritance
relation.
If the class hierarchy is not complete, a best guess is made.
Tries to calculate the most specific common supertype of the given types.
Tries to calculate the most specific common supertype of the given types.
If reflexive
is false
, the given types do not have to be in an
inheritance relation.
A list (set) of ObjectType
s that are not in an mutual
inheritance relation.
(I) Returns (if reflexive is true
) upperTypeBoundA
if it is a supertype
of at least one type of upperTypeBoundB
.
(II) Returns upperTypeBoundB
if upperTypeBoundA
is
a subtype of all types of upperTypeBoundB
. Otherwise a new upper type
bound is calculated and returned.
Given an upper type bound a most specific type that is a common supertype of the given types is determined.
Given an upper type bound a most specific type that is a common supertype of the given types is determined.
joinObjectTypesUntilSingleUpperBound(upperTypeBoundA: ObjectType,
upperTypeBoundB: ObjectType,reflexive: Boolean)
for further details.
Calculates the most specific common supertype of the given types.
Calculates the most specific common supertype of the given types.
If reflexive
is false
, no two types across both sets have to be in
an inheritance relation; if in doubt use true
.
A list (set) of ObjectType
s that are not in an
inheritance relation if reflexive is false
.
/* Consider the following type hierarchy: * Object <- Collection <- List * Object <- Collection <- Set * Object <- Externalizable * Object <- Serializable */ Object o = new ... if (...) { Set s = (Set) o; (( Externalizable)s).save(...) // => o(s) has to be a subtype of Set AND Externalizable } else { List l = (List) l; ((Serializable)l).store(...) // => o(l) has to be a subtype of List AND Serializable } // here, o is either a set or a list... hence, it is at least a Collection, // but we cannot deduce anything w.r.t. Serializable and Externalizable.
Selects all types of the given set of types that do not have any subtype in the given set.
Selects all types of the given set of types that do not have any subtype in the given set.
A set of types that contains for each value (type) stored in the
set all direct and indirect supertypes or none. For example, the intersection
of the sets of all supertypes (as returned, e.g., by
ClassHiearchy.allSupertypes
) of two (independent) types satisfies this
condition. If types
is empty, the returned leaf type is ObjectType.Object
.
which should always be a safe fallback.
Returns all classes that implement the given method by searching all subclasses
of receiverType
for implementations of the given method and also considering
the superclasses of the receiverType
up until the class (not interface) that
defines the respective method.
Returns all classes that implement the given method by searching all subclasses
of receiverType
for implementations of the given method and also considering
the superclasses of the receiverType
up until the class (not interface) that
defines the respective method.
An upper bound of the runtime type of some value. If the type
is known to be precise (i.e., it is no approximation of the runtime type)
then it is far more meaningful to directly call lookupMethodDefinition
.
The name of the method.
The method's descriptor.
Required to get a type's implementing class file. This method expects unrestricted access to the pool of all class files.
A function that returns true
, if the runtime type of
the receiverType
may be of the type defined by the given object type. For
example, if you analyze a project and perform a lookup of all methods that
implement the method toString
, then this set would probably be very large.
But, if you know that only instances of the class (e.g.) ArrayList
have
been created so far
(up to the point in your analysis where you call this method), it is
meaningful to sort out all other classes (such as Vector
).
Looks up the class file and method which actually defines the method that is referred to by the given receiver type, method name and method descriptor.
Looks up the class file and method which actually defines the method that is referred to by the given receiver type, method name and method descriptor. Given that we are searching for method definitions the search is limited to the superclasses of the class of the given receiver type.
This method does not take visibility modifiers or the static modifier into account. If necessary, such checks need to be done by the caller.
This method supports resolution of signature polymorphic methods
(in this case however, it needs to be checked that the respective invoke
instruction is an invokevirtual
instruction.)
Some(Method)
if the method is found. None
if the method
is not found. This can basically happen under two circumstances:
First, not all class files referred to/used by the project are (yet) analyzed;
i.e., we do not have all class files belonging to the project.
Second, the analyzed class files do not belong together (they either belong to
different projects or to incompatible versions of the same project.)
To get the method's defining class file use the project's respective method.
In case that you analyze static source code dependencies and if an invoke instruction refers to a method that is not defined by the receiver's class, then it might be more meaningful to still create a dependency to the receiver's class than to look up the actual definition in one of the receiver's super classes.
resolveFieldReference(org.opalj.br.ObjectType,java.lang.String,org.opalj.br.FieldType,org.opalj.br.ClassFileRepository):scala.Option[org.opalj.br.Field]
Resolves a symbolic reference to a field.
Resolves a symbolic reference to a field. Basically, the search starts with
the given class c
and then continues with c
's superinterfaces before the
search is continued with c
's superclass (as prescribed by the JVM specification
for the resolution of unresolved symbolic references.)
Resolving a symbolic reference is particularly required to, e.g., get a field's
annotations or to get a field's value (if it is static
, final
and has a
constant value).
The class (or a superclass thereof) that is expected to define the reference field.
The name of the accessed field.
The type of the accessed field (the field descriptor).
The project associated with this class hierarchy.
The field that is referred to; if any. To get the defining ClassFile
you can use the project
.
Resolution is final. I.e., either this algorithm has found the defining field or the field is not defined by one of the loaded classes. Searching for the field in subclasses is not meaningful as it is not possible to override fields.
,This implementation does not check for IllegalAccessError
. This check
needs to be done by the caller. The same applies for the check that the
field is non-static if get-/putfield is used and static if a get/putstatic is
used to access the field. In the latter case the JVM would throw a
LinkingException
.
Furthermore, if the field cannot be found, it is the responsibility of the
caller to handle that situation.
Tries to resolve a method reference as specified by the JVM specification.
Tries to resolve a method reference as specified by the JVM specification.
I.e., the algorithm tries to find the class that actually declares the referenced
method. Resolution of signature polymorphic method calls is also
supported; for details see lookupMethodDefinition
).
This method is the basis for the implementation of the semantics
of the invokeXXX
instructions. However, it does not check whether the resolved
method can be accessed by the caller or if it is abstract. Additionally, it is still
necessary that the caller makes a distinction between the statically
(at compile time) identified declaring class and the dynamic type of the receiver
in case of invokevirtual
and invokeinterface
instructions. I.e.,
additional processing is necessary on the client side.
The type of the object that receives the method call. The type must be a class type and must not be an interface type.
The resolved method Some(
METHOD)
or None
.
To get the defining class file use the project's respective method.
This method just resolves a method reference. Additional checks, such as whether the resolved method is accessible, may be necessary.
,Generally, if the type of the receiver is not precise the receiver object's subtypes should also be searched for method implementations (at least those classes should be taken into consideration that may be instantiated).
The set of all types which have no super type; that is all (pseudo) root types;
if the class hierarchy is complete then this set contains exactly one element and
that element must identify java.lang.Object
.
The set of all types which have no super type; that is all (pseudo) root types;
if the class hierarchy is complete then this set contains exactly one element and
that element must identify java.lang.Object
.
If we load an application and all the jars used to implement it or a library and all the library it depends on then the class hierarchy should not contain multiple root types. However, the (complete) JDK contains some references to Eclipse classes which are not part of the JDK.
Returns some statistical data about the class hierarchy.
A dump of the class hierarchy information in TSV format.
Returns the immediate superclass of the given object type, if the given type is known and if it has a superclass.
Returns the immediate superclass of the given object type, if the given
type is known and if it has a superclass. I.e., in case of java.lang.Object
None is
returned.
Returns the set of all classes/interfaces from which the given type inherits and for which the respective class file is available.
Returns the set of all classes/interfaces from which the given type inherits and for which the respective class file is available.
An Iterable
over all class files of all super types of the given
objectType
that pass the given filter and for which the class file
is available.
It may be more efficient to use foreachSuperclass(ObjectType,
ObjectType ⇒ Option[ClassFile])(ClassFile => Unit)
Returns Some(<SUPERTYPES>)
if this type is known and information about the
supertypes is available.
Returns Some(<SUPERTYPES>)
if this type is known and information about the
supertypes is available. I.e., if this type is not known None
is returned;
if the given type's superinterfaces are known (even if this class does not
implement (directly or indirectly) any interface) Some(Set(<OBJECTTYPES>))
is
returned.
Returns a view of the class hierarchy as a graph (which can then be transformed into a dot representation Graphviz).
Returns a view of the class hierarchy as a graph (which can then be transformed into a dot representation Graphviz). This graph can be a multi-graph if the class hierarchy contains holes.
Represents a project's class hierarchy. The class hierarchy only contains information about those classes that were explicitly added to it except of
java.lang.Object
; the typejava.lang.Object
is always part of the class hierarchy.Thread safety
This class is effectively immutable. Hence, concurrent access to the class hierarchy is supported.
Unless explicitly documented, it is an error to pass an instance of
ObjectType
to any method if theObjectType
was not previously added. If in doubt, first check if the type is known (isKnown/ifKnown).