Revisiting the classpath problems

In Chapter 1, Introducing Java 9 Modularity, we looked at two problems faced by our friends Jack and Amit:

  • Jack couldn't easily encapsulate internal library types and prevent use of that type outside the library, while retaining the ability to freely use them inside his own library
  • Amit couldn't reliably assemble a set of compiled Java code and guarantee that all the dependencies and imports of those types are sufficiently met before the program actually hits the dependency at runtime

Have we solved these problems with the module system? Thankfully, yes!

We've already seen how the Java module's encapsulation prevents certain types from being accessed outside the module, even if the type is public, unless the package they belong to is explicitly exported. Indeed, we applied the same concept to hide the BubbleSortUtilImpl class from external use. When it comes time to upgrade our library, should we feel the need to modify (or even remove) that class, we can rest assured that the only consumer of that code is in the library itself.

How about the second problem--runtime verification? It turns out, the Java runtime refers to the same module-info module descriptor (this time in .class format) to figure this out. You ran the Main class in the packt.addressbook module and it worked fine because the runtime found the dependent module packt.sortutil in the module path. Let's see what happens if it doesn't find it. If I were to delete the compiled sortutil directory in the out directory, and run packt.addressbook/packt.addressbook.Main again, notice the error you get:

$ java --module-path out --module packt.addressbook/packt.addressbook.Main
  
Error occurred during initialization of VM
java.lang.module.ResolutionException: Module sortutil not found,
required by addressbook
at java.lang.module.Resolver.fail(java.base@9/Resolver.java:841) at java.lang.module.Resolver.resolve(
java.base@9/Resolver.java:154)
...

The error message points out that the packt.sortutil module is not found, but the important thing to notice here is when the error is thrown. It's not when the class is loaded and the runtime tries to find the dependent types that it encounters this error. The error occurs right at the VM initialization time as the message clearly mentions. This is a huge advantage when it comes to reliability of your Java code. If there are potential errors, the runtime catches that right at initialization and not at some arbitrary point in time during execution.

One of the requirements that the module system was designed to meet is to achieve fidelity across phases. What does this mean? You've seen how the module descriptor enabled you to build modules, encapsulate types, and verify availability of the necessary dependencies by allowing you to specify the contract about each module. These benefits affect not only the compilation process of your code, but also the runtime process. The same module definition that lets the compiler know something is wrong when a required module is missing can also provide the runtime with the same information! Thanks to the module descriptor being compiled into the code as a class file, the Java runtime can also read the same descriptor and know well in advance if every module that is depended upon by the code that needs to be run is available. You get the same behavior and error checking across the compilation and execution phases.

..................Content has been hidden....................

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