Soot is designed in such a way that all the classes it is going to load should be loaded in an initial phase, known as "resolving". A number of parts of Soot are not designed to work well with new classes being loaded after they have built their data structures. For example, Soot needs a certain amount of the type hierarchy loaded before it tries to perform the Jimple typing algorithm.

As a result, it is not advisable to load classes at arbitrary times during the execution of Soot or a tool built on top of it. The purpose of this document is to explain how Soot decides which classes to load and how users and extenders of Soot can influence this process.

The first key point is that class loading is not just a binary switch where a given class must be either loaded or not loaded. The status of a class within Soot is measured along two axes. Firstly, a class can be loaded at multiple "levels", which controls how much of the structure and contents of a class has been processed by Soot. Secondly, there are multiple "kinds" of classes, depending on how Soot loaded them and what it intends to do with them. The concepts are mostly orthogonal, although some combinations of kind and level are invalid.

There are 4 levels, described in the list below. Levels build on previous levels, so a class at Signatures also supports all the operations of Hierarchy. For a class to be at a certain level often imposes constraints on the level of other classes; the Soot resolver takes care of these dependencies automatically.

Levels of resolving

These levels are defined as constants in SootClass?, with names SootClass.DANGLING, SootClass.HIERARCHY, SootClass.SIGNATURES and SootClass.BODIES. You should always refer to them by name rather than the underlying integer, for obvious robustness reasons.

Transitions between levels

Resolving modes

Soot has two different modes of resolving, normal and full. Which mode it is in affects how many classes are resolved and at what level this is done.

In normal mode, Soot starts from a certain root set of classes (the "application" and the "basic" classes, described below), and does the minimum to resolve them according to the constraints above. This mode is suitable for carrying out intraprocedural analysis only, but Soot startup is relatively fast.

In full mode, Soot starts from this same root set of classes, but they are all resolved at Bodies, and all classes referred to by them are resolved at Bodies, and so on, resolving everything in the transitive closure of referenced classes. This mode is suitable for carrying out interprocedural analysis; because Soot has to do much more work it takes significantly longer (a few seconds, normally) to startup in this mode. This is the old and simple algorithm used by Soot prior to version 2.2.0.

Full resolving mode can be turned on explicitly by the -full-resolver command-line option. It is also triggered by -ws (whole shimple), selecting the dava output format, and by -w (whole program). Note that -w itself is implied by various options, so there are a number of possible triggers for full resolving mode.

Kinds of classes

The set of Application classes is the set of classes specified on the Soot command-line. All other classes are either Library or Phantom, depending on whether an input file can be found for them or not. The kind of a class can be changed by methods in SootClass?, although it rarely makes sense to change a class to or from being a Phantom class.

If the -app command-line option is set, then all classes recursively referred to by those specified on the command-line also become Application classes, with the exception of those in certain packages which are normally part of the standard library. This set of packages can be affected by the -i and -x options. Note that -app and full resolving mode are orthogonal, although both will naturally increase the set of classes that are resolved at Bodies.

Specifying -include-all empties the default set of Library packages, and so to resolve all classes as far as possible, enable interprocedural analyses, and transform and write out classes for every class ever used by an application, one uses the combination -include-all -app -w. The -include-all, -i, and -x options only have an effect if -app is given. Specifying -include-all -app without -w will not enable interprocedural analyses but will write out every class needed, and will achieve the same effect with respect to resolution as -full-resolver would have: everything will get resolved to Bodies.

Basic classes

There are a number of classes which should always be loaded, even if the rules above do not specify that they should be. For example, any Java program might throw a ClassCastException? whether or not it is explicitly referred to by the program, so any analysis of exceptions will need to have this class loaded. This gives rise to the concept of "basic" classes. Soot specifies a number of such classes itself, and people building on top of Soot can add to this list by calling addBasicClass(classname, level) before invoking Soot's main method.

Basic classes are normally of kind "Library" unless something else causes them to be set as "Application". If the input for one cannot be found it could end up as "Phantom". The defaults are resolved on a class-by-class basis to either Hierarchy or Signatures.

List of relevant methods

loadNecessaryClasses is invoked when Soot's main method is called, so you only need to call it or loadBasicClasses yourself if you are not calling Soot's main.

The following methods are deprecated. If you use these after resolution is finished, an exception will be thrown if the class is not already loaded at the required level.