abstract class ProjectLike extends ClassFileRepository
Enables project wide lookups of methods and fields as required to determine the target(s) of an invoke or field access instruction.
- Self Type
- ProjectLike
- Source
- ProjectLike.scala
- Note
The current implementation is based on the correct project assumption; i.e., if the bytecode of the project as a whole is not valid, the result is generally undefined. Just one example of a violation of the assumption would be, if we have two interfaces which define a non-abstract method with the same signature and both interfaces are implemented by a third interface which does not override these methods. In this case the result of a
resolveMethodReference
is not defined, because the code base as a whole is not valid.
- Alphabetic
- By Inheritance
- ProjectLike
- ClassFileRepository
- AnyRef
- Any
- Hide All
- Show All
- Public
- Protected
Instance Constructors
- new ProjectLike()
Abstract Value Members
- abstract val MethodHandleClassFile: Option[ClassFile]
The class file of
java.lang.invoke.MethodHandle
, if available. - abstract val MethodHandleSubtypes: Set[ObjectType]
The set of all subtypes of
java.lang.invoke.MethodHandle
; in particular required to resolve signature polymorphic method calls. - abstract val ObjectClassFile: Option[ClassFile]
The class file of
java.lang.Object
, if available. - abstract val VarHandleClassFile: Option[ClassFile]
The class file of
java.lang.invoke.VarHandle
, if available. - abstract val VarHandleSubtypes: Set[ObjectType]
The set of all subtypes of
java.lang.invoke.VarHandle
; in particular required to resolve signature polymorphic method calls. - abstract val allClassFiles: Iterable[ClassFile]
- Attributes
- protected[this]
- abstract def classFile(objectType: ObjectType): Option[ClassFile]
- Definition Classes
- ClassFileRepository
- implicit abstract val classHierarchy: ClassHierarchy
- implicit abstract val config: Config
- abstract val instanceMethods: Map[ObjectType, ArraySeq[MethodDeclarationContext]]
Returns the set of all non-private, non-abstract, non-static methods that are not initializers and which are potentially callable by clients when we have an object that has the specified type and a method is called using org.opalj.br.instructions.INVOKEINTERFACE, org.opalj.br.instructions.INVOKEVIRTUAL or org.opalj.br.instructions.INVOKEDYNAMIC.
Returns the set of all non-private, non-abstract, non-static methods that are not initializers and which are potentially callable by clients when we have an object that has the specified type and a method is called using org.opalj.br.instructions.INVOKEINTERFACE, org.opalj.br.instructions.INVOKEVIRTUAL or org.opalj.br.instructions.INVOKEDYNAMIC.
The array of methods is sorted using MethodDeclarationContextOrdering to enable fast look-up of the target method. (See MethodDeclarationContext's
compareAccessibilityAware
method for further details.)- Attributes
- protected[this]
- implicit abstract def logContext: LogContext
- Definition Classes
- ClassFileRepository
- abstract val nests: Map[ObjectType, ObjectType]
Returns the nest host (see JVM 11 Spec.
Returns the nest host (see JVM 11 Spec. 5.4.4) for the given type, if explicitly given. For classes without an explicit NestHost or NestMembers attribute, the type itself is the nest host, but this is NOT recorded in this map.
- abstract val overridingMethods: Map[Method, Set[Method]]
Stores for each non-private, non-initializer method the set of methods which override a specific method.
Stores for each non-private, non-initializer method the set of methods which override a specific method. If the given method is a concrete method, this method is also included in the set of
overridingMethods
.- Attributes
- protected[this]
Concrete Value Members
- final def !=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def ##: Int
- Definition Classes
- AnyRef → Any
- final def ==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def asInstanceOf[T0]: T0
- Definition Classes
- Any
- def clone(): AnyRef
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.CloneNotSupportedException]) @native() @IntrinsicCandidate()
- final def eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- def equals(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef → Any
- def findMaximallySpecificSuperinterfaceMethods(superinterfaceTypes: UIDSet[ObjectType], name: String, descriptor: MethodDescriptor, analyzedSuperinterfaceTypes: UIDSet[ObjectType]): (UIDSet[ObjectType], Set[Method])
Computes the maximally specific superinterface method with the given name and descriptor
Computes the maximally specific superinterface method with the given name and descriptor
- superinterfaceTypes
A set of interfaces which potentially declare a method with the given name and descriptor.
- def findMaximallySpecificSuperinterfaceMethods(superinterfaceType: ObjectType, name: String, descriptor: MethodDescriptor, analyzedSuperinterfaceTypes: UIDSet[ObjectType] = UIDSet.empty): (UIDSet[ObjectType], Set[Method])
Computes the set of maximally specific superinterface methods with the given name and descriptor.
Computes the set of maximally specific superinterface methods with the given name and descriptor.
- Note
This method does not consider methods defined by
java.lang.Object
! Those methods have precedence over respective methods defined by superinterfaces! A corresponding check needs to be done before calling this method.
- final def getClass(): Class[_ <: AnyRef]
- Definition Classes
- AnyRef → Any
- Annotations
- @native() @IntrinsicCandidate()
- def hasVirtualMethod(objectType: ObjectType, method: Method): Answer
Tests if the given method belongs to the interface of an object identified by the given
objectType
.Tests if the given method belongs to the interface of an object identified by the given
objectType
. I.e., returnstrue
if a virtual method call, where the receiver type is known to have the givenobjectType
, would lead to the direct invocation of the givenmethod
. The given method can be an inherited method, but it will never returnYes
if the given method is overridden byobjectType
or a supertype of it which is a sub type of the declaring type ofmethod
.- Note
The computation is based on the computed set of instanceMethods and generally requires at most O(n log n) steps where n is the number of callable instance methods of the given object type; the class hierarchy is not traversed.
- def hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native() @IntrinsicCandidate()
- def instanceCall(callerClassType: ObjectType, receiverType: ReferenceType, name: String, descriptor: MethodDescriptor): Result[Method]
Returns the (instance) method that would be called when we have an instance of the given receiver type.
Returns the (instance) method that would be called when we have an instance of the given receiver type. I.e., using this method is suitable only when the runtime type, which is the receiver of the method call, is precisely known!
Examples
class A {def foo() = {} } class B extends A {/*inherits, but does not override foo()*/} class C extends B { def foo() = {} } val b = new B(); b.foo() // <= in this case the method defined by A will be returned. val c = new C(); c.foo() // <= in this case the method defined by C will be returned.
This method supports default methods and signature polymorphic calls; i.e., the descriptor of the retuned methods may not be equal to the given method descriptor.
- callerClassType
The object type which defines the method which performs the call. This information is required if the call target has (potentially) default visibility. (Note that this - in general - does not replace the need to perform an accessibility check.)
- receiverType
A class type or an array type; never an interface type.
- def interfaceCall(callerType: ObjectType, declaringClass: ObjectType, name: String, descriptor: MethodDescriptor): Set[Method]
Returns the methods that may be called by an org.opalj.br.instructions.INVOKEINTERFACE call if the precise runtime type is not known.
Returns the methods that may be called by an org.opalj.br.instructions.INVOKEINTERFACE call if the precise runtime type is not known. (If the precise runtime type is known, use
instanceCall
to get the target method.)- returns
The set of potentially called methods. The set will be empty if the target class is not defined as part of the analyzed code base.
- Note
Caching the result (in particular when the call graph is computed) is recommended as the computation is expensive. In other words, this function is meant to be used as a foundation for call graph construction algorithms.
,Keep in mind that the following is legal (byte)code:
class X { void m(){ System.out.println("X.m"); } } interface I { void m(); } class Z extends X implements I {}
Hence, we also have to consider inherited methods and just considering the methods defined by subclasses is not sufficient! In other words, the result can contain methods (here,
X.m
) defined by classes which are not subtypes of the given interface type!
- def interfaceCall(callerType: ObjectType, i: INVOKEINTERFACE): Set[Method]
- final def isInstanceOf[T0]: Boolean
- Definition Classes
- Any
- def isSignaturePolymorphic(definingClassType: ObjectType, name: String, descriptor: MethodDescriptor): Boolean
Returns true if the signature is a signature polymorphic method for the given class type.
Returns true if the signature is a signature polymorphic method for the given class type. (See JVM 9 Spec. for details.)
- def isSignaturePolymorphic(definingClassType: ObjectType, descriptor: MethodDescriptor): Boolean
Returns true if the descriptor is a signature polymorphic method for the given class type.
Returns true if the descriptor is a signature polymorphic method for the given class type. (See JVM 9 Spec. for details.)
- def isSignaturePolymorphic(definingClassType: ObjectType, method: Method): Boolean
Returns true if the method defined by the given class type is a signature polymorphic method.
Returns true if the method defined by the given class type is a signature polymorphic method. (See JVM 9 Spec. for details.)
- def lookupVirtualMethod(callingContextType: ObjectType, receiverType: ObjectType, name: String, descriptor: MethodDescriptor): Result[MethodDeclarationContext]
Looks up the method (declaration context) which is accessible/callable by an org.opalj.br.instructions.INVOKEVIRTUAL or org.opalj.br.instructions.INVOKEINTERFACE call which was done by a method belonging to
callingContextType
.Looks up the method (declaration context) which is accessible/callable by an org.opalj.br.instructions.INVOKEVIRTUAL or org.opalj.br.instructions.INVOKEINTERFACE call which was done by a method belonging to
callingContextType
. ThecallingContextType
is only relevant in case the target method has default visibility; in this case it is checked whether the caller belongs to the same context.- returns
Success if the method is found; Empty$ if the method cannot be found and Failure$ if the method cannot be found because the project is definitively inconsistent.
Failure$
is used on a best-effort basis.
- Note
This method uses the pre-computed information about instance methods and, therefore, does not require a type hierarchy based lookup.
,It supports the lookup of polymorphic methods.
- final def ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- def nonVirtualCall(callerClassType: ObjectType, i: NonVirtualMethodInvocationInstruction): Result[Method]
- final def notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native() @IntrinsicCandidate()
- final def notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native() @IntrinsicCandidate()
- def overriddenBy(m: Method): Set[Method]
Returns the set of methods which directly override the given method.
Returns the set of methods which directly override the given method. Note that
overriddenBy
is not context aware. I.e., if a given methodm
is an interface method, then it may happen that we have an implementation of that method in a class which is inherited from a superclass which is not a subtype of the interface. That method - since it is not defined by a subtype of the interface - would not be included in the returned set. An example is shown next:class X { void m(){ System.out.println("X.m"); } interface Y { default void m(){ System.out.println("Y.m"); } class Z extends X implements Y { // Z inherits m() from X; hence, X.m() (in this context) "overrides" Y.m(), but is not // returned by this function. To also identify X.m() you have to combine the results // of overridenBy and instanceMethods(!). }
- def requiredJVMVersion: Int
Returns the minimum version number of the JVM required to run the code of the project, i.e., the maximum class file major version number of any class file in the project.
- def resolveAllMethodReferences(declaringClassType: ReferenceType, name: String, descriptor: MethodDescriptor): Set[Method]
Resolves a method reference to all possible methods.
Resolves a method reference to all possible methods. I.e., this is identical to
resolveMethodReference
orresolveInterfaceMethodReference
for class and interface types respectively except for the case where there are multiple maximally specific interface methods in which case all of them are returned instead of only a single one.- declaringClassType
The type of the object that receives the method call. The type may be a class or interface type.
- returns
The set of resolved methods; empty if the resolution fails, more than one if resolution finds several maximally specific interface methods - in the latter case it is not possible to call the method on objects of the declaring class type, but only on subclasses overriding the method uniquely.
- def resolveClassMethodReference(receiverType: ObjectType, name: String, descriptor: MethodDescriptor): Result[Method]
Resolves a symbolic reference to a method defined by a class (not interface) type.
Resolves a symbolic reference to a method defined by a class (not interface) type.
- returns
org.opalj.Success
(method)
if the method was found;Empty
if the project is incomplete and the method could not be found;Failure
if the method could not be found though the project is seemingly complete. I.e., ifFailure
is returned the method is not defined by a concrete class and is either a default method defined by an interface or the analyzed code basis is inconsistent.
- final def resolveFieldReference(fieldAccess: FieldAccess): Option[Field]
- def resolveFieldReference(declaringClassFile: ClassFile, fieldName: String, fieldType: FieldType): Option[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 withc
's superinterfaces before the search is continued withc
'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).- declaringClassFile
The class (or a superclass thereof) that is expected to define the specified field.
- fieldName
The name of the field.
- fieldType
The type of the field (the field descriptor).
- Note
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 aLinkingException
. Furthermore, if the field cannot be found, it is the responsibility of the caller to handle that situation.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.
- final def resolveFieldReference(declaringClassType: ObjectType, fieldName: String, fieldType: FieldType): Option[Field]
- def resolveInterfaceMethodReference(i: INVOKEINTERFACE): Option[Method]
See #resolveInterfaceMethodReference(declaringClassType:* for details.
- def resolveInterfaceMethodReference(declaringClassType: ObjectType, name: String, descriptor: MethodDescriptor): Option[Method]
- def resolveMethodReference(i: INVOKEVIRTUAL): Option[Method]
See #resolveMethodReference(declaringClassType:* for details.
- def resolveMethodReference(declaringClassType: ReferenceType, name: String, descriptor: MethodDescriptor, forceLookupInSuperinterfacesOnFailure: Boolean = false): Option[Method]
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.
This method can be used as 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 ofinvokevirtual
andinvokeinterface
instructions. I.e., additional processing is necessary on the client side.- declaringClassType
The type of the object that receives the method call. The type must be a class type and must not be an interface type. No check w.r.t. a potential
IncompatibleClassChangeError
is done by this method.- forceLookupInSuperinterfacesOnFailure
If true (default: false) the method tries to look up the method in a super interface if it can't find it in the available super classes.
- returns
The resolved method
Some(
METHOD)
orNone
. (To get the defining class file use the project's respective method.)
- Note
This method just resolves a method reference. Additional checks, such as whether the resolved method is accessible, may be necessary.
- def specialCall(callerClassType: ObjectType, initialDeclaringClassType: ObjectType, isInterface: Boolean, name: String, descriptor: MethodDescriptor): Result[Method]
Returns the instance method/initializer which is called by an invokespecial instruction.
Returns the instance method/initializer which is called by an invokespecial instruction.
- returns
One of the following three values:
- org.opalj.Success
(method)
if the method was found; Failure
if the project is inconsistent; i.e., the target class file is found, but the method cannot be found.Failure
is returned on a best effort basis.Empty
.
- org.opalj.Success
- Note
Virtual method call resolution is not necessary; the call target is either a constructor, a method in the given class or a super method/constructor. However, in the first and last case it may be possible that we can't find the method because of an inconsistent or incomplete project.
- def specialCall(callerClassType: ObjectType, i: INVOKESPECIAL): Result[Method]
- def staticCall(callerClassType: ObjectType, declaringClassType: ObjectType, isInterface: Boolean, name: String, descriptor: MethodDescriptor): Result[Method]
Returns the method that will be called by the respective invokestatic call.
Returns the method that will be called by the respective invokestatic call.
- returns
org.opalj.Success
(method)
if the method was found;Failure
if the project is inconsistent.Empty
if the method could not be found in the available classes (i.e., the project is incomplete).
- def staticCall(callerClassType: ObjectType, i: INVOKESTATIC): Result[Method]
Returns the method which will be called by the respective org.opalj.br.instructions.INVOKESTATIC instruction.
- final def synchronized[T0](arg0: => T0): T0
- Definition Classes
- AnyRef
- def toString(): String
- Definition Classes
- AnyRef → Any
- def virtualCall(callerType: ObjectType, declaringType: ReferenceType, name: String, descriptor: MethodDescriptor): Set[Method]
Returns the set of methods that may be called by an invokevirtual call, if the receiver type is unknown or effectively encompasses all subtypes it is recommended to use instanceCall.
Returns the set of methods that may be called by an invokevirtual call, if the receiver type is unknown or effectively encompasses all subtypes it is recommended to use instanceCall.
- Note
As in case of instance call, the returned method may have a different descriptor if we have a signature polymorphic call!
- def virtualCall(callerType: ObjectType, i: INVOKEVIRTUAL): Set[Method]
Convenience method; see
virtualCall(callerPackageName:String,declaringType:ReferenceType*
for details. - final def wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
Deprecated Value Members
- def finalize(): Unit
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.Throwable]) @Deprecated
- Deprecated