What are the main advantages of using the Java 9+ modularization feature?

Question:

Starting with Java 9 we have the possibility to modularize our application using the so-called Java Platform Module System

Before Java 9, modularization was done purely through JARs, where we had several libraries, and it was possible to modularize the application with several JARs (for example, create JARs containing only entities, containing utilities, annotations…)

Thus, I raise the following questions:

  1. What expressive gain do we have when using the new module system?
  2. In terms of complexity, how easy is its applicability in large projects that are already running on Java 8 for example?
  3. During library updates, we sometimes come across conflicts between versions and dependencies. In this modularization scenario, doesn't this problem become more common?

Answer:

What expressive gain do we have when using the new module system?

Here, from what I could read and taste (I couldn't take a big sip, just a taste on the tip of my tongue) of Jigsaw, there are two main advantages:

  1. you can create classes that you won't expose and use in any package in your module
  2. class search optimization by classpath

The first part I even felt when trying to put legacy code to run with Java 12: Oracle, now, decided to actually hide its intimate implementations.

I don't know if you remember, but do you know the sun.java.* packages? Well then, they were internal packages that should only be consumed by the Sun/Oracle JRE/JDK. In theory, no program designed to run on Java should depend on these packages. What was it possible to do with Jigsaw? Remove them from the path =) So what happened to a legacy library I had that accessed sun.misc.BASE64Encoder ? Gave ClassNotFoundException and the system stopped.

Honestly, did I think it was bad? No, oddly enough, I didn't think it was bad. Just curious. As the code to this library was lost in space/time (and it is a deprecated artifact), it only served as another push to abandon it.

Now, how do you get an improved performance when searching the classpath ?

Let's go back to the class I no longer had access to, sun.misc.Base64Encoder . When in a module, the first search will be for classes in that module. So, in the case of the java.base module (let's pretend, ok? I don't know what the real module would be), at one point it was necessary to access the sun.misc.Base64Encoder class. The processing was inside the java.base module, so the first thing it does is ask inside the module who is sun.misc.Base64Encoder and it finds this class, public.

Now, we are on my implementation. Suppose it is properly ported to Java 9 and tries to access sun.misc.Base64Encoder . The first thing ClassLoader will try to do is see, inside the module I'm located in, if there is any class with this signature. The answer will be no. So, at this point, I also go through all the other modules in the classpath that I classpath to use (or inherit via transitive ) and see if there's anyone who provides the sun.misc package, without going deep into them for further inspection. Perhaps one or another Java 8-libraries offer some resistance because, by default, they behave as if they were modules with all available packages.

See how search time is reduced using modules?

In terms of complexity, how easy is its applicability in large projects that are already running on Java 8 for example?

Can you modulate your program well? If so, the first step will be to provide a module-info.java with the following information:

  1. what modules do i depend on? requires
  2. for each required module, should i make it available to third parties that import from my module or not? transitive
  3. which packages will I expose programmatically so that it is seen as part of the classpath for other modules? exports
  4. which classes would you like to be accessible via reflection , even if it is not "available" to access directly via ClassLoader´? `

This opens step is the most delicate when using a framework that relies heavily on reflections (like Spring, Hibernate, MyBatis etc).

By setting all this up correctly, and by properly separating the modules, the rest should flow naturally. I particularly see more Jigsaw applications for libraries, but I haven't seen reasons to prevent an application from being separated into modules.

Now, these definitions are not trivial to make. Perhaps a re-engineering of the original code to hide the implementation by moving it to another package is necessary.

During library updates, we sometimes come across conflicts between versions and dependencies. In this modularization scenario, doesn't this problem become more common?

One advantage this scheme provides is that it can have multiple classes with the same name. The only requirement for this is that they are not from exported packages. A very well thought-out library might be able to make proper use of this, but most are lacking with Java 8 target .

Another point is that this does not exempt dependency management by Maven or Gradle (or whatever you use for this purpose). So, I don't see how using modules would alleviate these update issues (with possible exceptions from classes with the same signature in two distinct modules).


References:

Scroll to Top