One of the most common tasks when implementing static analyses is to get information about the inheritance relation between different classes, to traverse all super/sub classes/interfaces or to compute the least upper bound given some classes. Support for answering such questions or for processing a project's class hierarchy is directly provided by OPAL's org.opalj.br.ClassHierarchy
. The easiest way to get the class hierarchy is to first instantiate a project and then ask the project for the class hierarchy.
import org.opalj.br._ ; import org.opalj.br.analyses._ ; import java.io.File
val projectJAR = "./OPAL/bi/target/scala-2.13/resource_managed/test/method_types.jar"
implicit val p = Project(new File(projectJAR),org.opalj.bytecode.RTJar)
val classHierarchy = p.classHierarchy
The class hierarchy, e.g., directly makes the information about a type's super/sub types available:
def subtypeInformation(ObjectType) : SubtypeInformation
def supertypeInformation(ObjectType) : SupertypeInformation
To get, e.g., all subtypes of java.io.Serializable
, it is sufficient to query the subtypes information:
val subtypesOfSerializable = classHierarchy.subtypeInformation(ObjectType("java/io/Serializable"))
Recall that in Java bytecode package names are separated using "/" and not "." as used in Java/Scala/... source code.
OPAL's class hierarchy supports partial class hierarchies and - in case that a class hierarchy is incomplete – generally follows a best-effort approach to determine sub-/supertype relations. In particular, when
isSubtypeOf
is used,java.lang.Object
will always be treated as the supertype and an interface will never be the subtype of a class type, even if the supertype hierarchy for the interface is incomplete. As a matter of fact, the standard JDK/rt.jar contains references to classes that are not delivered as part of the JDK and therefore the class hierarchy is basically always incomplete.
If you don't know whether a given type is known to the class hierarchy, you should call the get
method to avoid potential NoSuchElementExceptions
.
classHierarchy.subtypeInformation.get(ObjectType("java/io/Serializable")).foreach{subtypeInformation => ... }