Skip to content

Latest commit

 

History

History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Static Linkage Checker

Static Linkage Checker is a tool that finds static linkage errors on a class path and reports the errors to the console. It scans the class files in the class path for references to other classes and reports any reference that cannot be satisfied in the class path. It can report all such unsatisfied references or only those that are reachable from a given set of entry point classes.

Use Cases

There are two use cases for Static Linkage Checker:

  • For library/application developers the tool finds static linkage errors in their projects, and will help to avoid incompatible versions of libraries in their dependencies.

  • For organizations that provide multiple libraries developed by different teams, the tool helps to ensure that users depending on the libraries will not see any static linkage errors at runtime.

Approach

  1. The tool takes a class path as required input. This class path is called the input class path and is separate from the runtime class path of the tool itself. The tool operates on the input class path to find linkage errors.

  2. The tool extracts all symbolic references from the all class files in the class path.

  3. The tool records static linkage errors for symbolic references which cannot be satisfied in the class path.

  4. Optionally, the user can specify a subset of elements in the class path as entry points. In that case, the tool will list only those references that are reachable from the classes in the entry points.

  5. At the end, the tool outputs a report on the linkage errors.

Input

The input of the tool is either the Maven coordinates of a BOM, a list of Maven coordinates, or a list of class and jar files in the filesystem. All of these inputs are converted to a class path for the static linkage check, which is the input class path.

When the input is a Maven BOM, the elements in the BOM are converted to a list of Maven coordinates. If the BOM imports another BOM, the elements of the second BOM are recursively added to the list of Maven coordinates. This list of Maven coordinates is handled in the same way as a directly-provided list of coordinates (see below).

When the input is a list of Maven coordinates, they are resolved to a list of jar files that consists of the artifacts and their dependencies, through a Maven dependency graph. This list of jar files is handled in the same way as a directly-provided list of jar files (see below).

When the input is a list of class and jar files, they are used directly as the input class path.

Output

The tool reports static linkage errors for the input class path. Each of the static linkage errors contains information on the source class and the destination class of the reference, and has one of the three types: missing class, missing method, or missing field.

Class Reference Graph and Reachability

In order to provide a diagnosis in the output report, the tool builds a class reference graph, and annotates linkage errors with reachability from entry point classes. Optionally the tool outputs a report including only reachable static linkage errors. The tool allows users to choose the scope of entry point classes:

  • Classes in the target project: when the scope of the entry point is only the classes in the target project, it ensures that the current functionality used in the dependencies will not cause static linkage errors. The output may fail to report potential static linkage errors, which would be introduced by starting to use a previously unreachable class in one of the dependencies.

  • With direct dependencies of the target project: when the scope of the entry point is the classes in the target project and the all classes in the direct dependencies of the project, it ensures that functionality of the dependencies will not cause static linkage errors. The output may contain linkage errors for unreachable classes from user's perspective.

  • All classes in the input class path: when reachability check is off, then all static linkage errors from all classes in the classpath, regardless of the reachability, are reported.

Maven Dependency Graph

A Maven dependency graph is a graph data structure where

  • Node: a node is a Maven artifact identified by Maven coordinates such as com.example.foo:bar:1.5.4. A node may be marked unavailable when the artifact is not available in Maven repositories.

  • Edge: a directed edge is a dependency from one Maven artifact (source of the edge) to another Maven artifact (target of the edge).

    A dependency has a boolean attribute optional and an enum attribute scope, among other properties listed in POM Reference: Dependencies.

    Self-loops are not possible. A parallel edge is allowed but is dropped in the model.

Comparison with Maven Dependency Trees by pom.xml

Compared to a Maven dependency tree retrieved by a pom.xml through RepositorySystem.resolveDependencies, a Maven dependency graph has the following differences:

  • A Maven dependency tree cannot have multiple versions of a Maven artifact, whereas a Maven dependency graph can have them.
  • A Maven dependency tree does not have transitive scope: provided dependencies under a scope: provided dependency, whereas a Maven dependency graph can have them.
  • A Maven dependency tree does not contain a cycle, whereas a Maven dependency graph can contain cycles.

Graph Construction

Given an ordered list of Maven artifacts, DependencyGraphBuilder constructs a Maven dependency graph in the following steps:

  1. Start with a graph with nodes of the Maven artifacts in the list. The nodes are called initial nodes.
  2. Pick up an unvisited node which is not marked unavailable in a graph in breadth-first manner.
  3. By reading dependencies of the node,
    • add new nodes corresponding to the target Maven artifacts, identified by Maven coordinates, if not present.
    • add edges from the source node to the target nodes of the Maven artifacts.
  4. Repeat Step 2-3, until all nodes are visited in the breadth-first traversal.

Graph Construction Failure

A graph construction may fail when there is a problem.

Unavailable Artifact

A Maven artifact may be unavailable through Maven repositories. Such nodes are marked unavailable at Step 3 of a graph construction.

Given a set of initial nodes, a node is called optional when the path from the initial nodes to the artifact contains an optional node. A node is called provided if the path contains a scope: provided dependency.

When there is an unavailable Maven artifact and it is not optional or provided for the initial nodes, the graph construction fails.

Unsatisfied Version Constraints

A dependency element in pom.xml may have a version range specification. Each of the specifications creates a version constraint.

When there is a version constraint that cannot be satisfied, the graph construction fails.

Class Path Generation through Maven Dependency Graph

A class path (list of jar files of Maven artifacts) can be generated from a Maven dependency graph. A class path is built by picking up Maven artifacts by a breadth-first traversal. The traversal starts from the initial nodes of a Maven dependency graph.

During the pick-up,

  • duplicate artifacts identified by Maven coordinates are discarded.
  • nodes marked as unavailable are skipped.

When there are multiple versions of a Maven artifact identified by Maven coordinates without the version part, a version is picked up using one of the following strategies:

  • Maven dependency mediation strategy: the first version encountered during the breadth-first traversal is selected.
  • Gradle dependency mediation strategy: the highest version among a Maven dependency graph is selected.