Module resolution process

Before we get into the details of the linking process and what it can do for us, let's understand an important step that happens every time you compile and execute a modular Java application. This is a step called module resolution.

Traditionally (pre-Java 9), the Java compiler and Java runtime would to look at a set of folders and JAR files that form the classpath. The classpath is a configurable option that you pass to the compiler during compilation and to the runtimes during execution. In order to have any class file be under the purview of the compiler or runtime, you'd need to first place it in the classpath. Once it's there, every Java type is available for the compiler or the runtime.

Things are different with modules. We don't have to use the generic classpath anymore. Since every module defines its inputs and outputs, there's now an option to know exactly what portion of the code is needed at any time.

Consider the following module dependency graph:

Let's assume that you have the modules A, B, C, D, and E in the module path. Let's imagine that you are playing the role of the Java runtime, and you want to execute the main method in module C. What is the minimal set of modules that are required for this to happen? You'll obviously need module C, since that has the main method. Next you'll need its dependencies, modules B and D. Next you'll need those modules' dependencies as well, which in this case is module A, which B depends on:

Using this process, it's safe to say that the minimum set of modules required to execute a main type in module C is A, B, C, and D--module E is unnecessary.

Let's repeat the exercise, but this time to execute a type in module E. This time, we'll just need modules E and D; all other modules can be skipped:

Now why are we doing this? What's the advantage of finding this minimal set of modules? Contrast this with the older classpath model where every type in the classpath is a part of the application, and any type could be in use. There's no way for the compiler and runtime to figure out where a given type exists unless it scans the entire classpath. That's not the case anymore! Since both the compiler and runtime now have a precise idea about what part of the code base is needed to execute anything and what part is not, it puts this advantage to good use, as we'll soon see. But in order to get this information, the platform runs a process of resolving modules, which is, in principle, similar to what we did in the preceding example. This process is called the module resolution process.

In graph theory, this process is referred to as finding transitive closure. Given a graph, the idea is to find a set of nodes that are reachable from a given node. The graph on which we perform transitive closure should be what's called a directed acyclic graph (DAG). The graph should be directed, in that the relationships between nodes are directional (with arrows), and acyclic, in that there shouldn't be cyclical relationships. Does the DAG remind you of any graphs you've seen recently? Yes! The Java module graph is a great example of a directed acyclic graph!
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.93.141