Skip to content

Naming Java Entities

Manu Sridharan edited this page Oct 7, 2021 · 6 revisions

In bytecode, there can be more than one name for a single given entity that arises at runtime.

For example, suppose you have classes A and B in package foo, where A extends B. Further, neither A nor B overrides java.lang.Object.toString().

The following are all legal names for a method that might arise in the bytecode:

  • < Application, Lfoo/A, toString() >
  • < Application, Lfoo/B, toString() >
  • < Application, Ljava/lang/Object, toString() >
  • < Primordial, Ljava/lang/Object, toString() >

However at run-time, these will all be resolved to a single entity: < Primordial, Ljava/lang/Object, toString()>.

In WALA, an IMethod represents the unique entity that will arise at run-time, while a MethodReference can represent any of the possible names that arise in the bytecode.

Similarly, an IClass represents the unique entity that will arise at run-time, while a TypeReference can represent any of the possible names for a type that arise at runtime. Note that in Java the unique name of a class is actually a pair of a classloader x packagename.typename. So a TypeReference actually consists of a ClassLoaderReference x TypeName (see Class Hierarchy Basics for further details).

There's similar logic between FieldReference and IField, and ClassLoaderReference and IClassLoader.

A ClassHierarchy object allows for resolving references to run-time entities (e.g., getting an IMethod object from a MethodReference): see ClassHierarchy.resolveMethod(), ClassHierarchy.resolveField(), etc. (see Class Hierarchy Basics for more details on class hierarchies and class loaders).

Note that most names of entities (e.g. TypeReference, TypeName, MethodReference) are canonicalized via hash-consing, to save space.