Ravi Gupta
4 min readJul 2, 2018

This is the third edition of the series. For second edition, click here.

Module Descriptors

Modules are defined by module descriptors. So, let’s have a look at an example of module descriptors.

Module descriptor for java.base

Now looking at the module descriptors above for java.base, it lives in a file called module-info.java. The most important part of the module-info.java is the integration of the name of the module. In this case, by the module keyword followed by the name java.base. In the body of the module declaration, we can have additional statements describing more information about the module itself. In the case of java.base, we know there are some packages that needs to be public. Now, by default, any package inside a module is not public. It is not accessible by other modules. If you want to give other modules access to some packages, you need to export them. That’s what we see above. There is an export statement for every package that you want to expose from your module to the outside world. Note that there is not statement referring to internal packages. This is because by default, any packages that is not listed as an exported package is encapsulated in a module and are not accessible by other modules.

Module descriptor for java.sql

Take for an example of java.sql module. This module has two dependencies. We are exporting some packages from java.sql. The interesting part is there in dependencies. You add a require statement to the module. There is one big difference between export statement and require statement that I want to highlight because it may not be immediately apparent. The export statement takes package name as parameter, whereas the require statement takes module name as parameter. So, module export packages, but require other modules.
Now, we know how to create module descriptors.

Module Resolution

Module Resolution process

When we compile and run Java 9 application, it kicks off with a so-called root module which is specified by the user. The goal of module resolution process is to end up with a set of resolved module that are necessary to run the application. This set should include all modules needed to run the application, but nothing more than that. Now of course, where we start the resolution process, the root module is the part of the resultant module set. What happens next is that the module system inspects the module descriptor of this module and all its dependencies to the set of resolved module as well. The process now recursively continues with finding the dependencies of the newly module added to the set. The search stops when there are no more dependencies from the module in the set to other modules, which means, we are done with the module resolution and we have our final set of modules to run the application.

Module Resolution properties

The modules resolution process is one of our biggest allies in the search for reliable applications. It checks the module path that we provide, for correctness. If there are any module missing, it will detect that. Module resolution takes place both at compile and at runtime, so if you have incomplete module path at compile time, you will be warned by the compiler as well and when starting your application, if anything goes wrong during module resolution process, you will get an error ahead of time. It is applied to both application and platform modules. After the resolver is done, you will have a complete view of all the modules needed to run the application. It even rejects multiple version of the same module if they are encountered in a directory of the module path. We can run the resolution multiple times for multiple root modules and combining the resulting module sets into single set.

In the next chapter, we will look into a special relation called readability.

Click here, for next edition.

source:
https://www.geekboots.com
https://www.pluralsight.com

Ravi Gupta

Hard work beats talent when talent fails to work hard.