Programming Chi

Tomasz Fijałkowski's programming blog.

Quick introduction to Java 9 modularization

The new version of Java is fast approaching. The official release is scheduled for the 27th of July 2017. However, you can already use the early access version to play with the new features. In this post, I’d like to quickly introduce the modularization of Java 9.

Modularization by example

Modularization really matters, nonetheless, there is no space in this brief post to discuss all its features in detail. So let’s quickly start with an example of module definition. Each module in Java 9 requires a module-info.java file containing the module descriptor. The content of an exemplary module-info.java is illustrated below:

module module.name {                                   # 1
    exports package.name.a;                            # 2
    exports package.name.b to other.module.name.a;     # 3
    requires other.module.name.b;                      # 4
}

This short example presents the basic module descriptor syntax. Let’s analyze it line by line.

Module name

The first line contains the module keyword followed by the module name - module.name in the given example. Module naming convention is similar to package convention - reversed domain notation, e.g., com.organization.project.

Module API

The second line declares that classes from package.name.a may be accessible for other modules. The module descriptor can export multiple packages, each on a separate line.

Restricted API

Line #3 declares that the package package.name.b is accessible only for other.module.name.a. This functionality should be used carefully as it breaks the rule that a module knows only its dependent modules. It also increases coupling of modules.

Module dependency

The last line contains information about the module dependencies. In the provided example, the module module.name depends on the other.module.name.b module and has access to its exported packages.

Rules of modularization

Modules in Java 9 provide strong encapsulation and, together with the standard access modifiers (public, protected, default, private), make modularization powerful. I’d like to mention some restrictions and facilities that come with modularization.

Firstly, cycles between modules (on the compilation level) are prohibited. It’s a limitation, but no one should cry because of that. Cycles, in general, are a sign of bad design.

Secondly, even if module encapsulation is controlled on compile and runtime level, you can break it using the reflection API and freely use debug tools.

Thirdly, all modules have an implicit dependency on the java.base module, and it doesn’t have to be specified in the module descriptor. The implicit dependency on java.base is similar to the implicit import of java.lang.String class.

Fourthly, due to backward compatibility, every class not placed in the modules goes to the unnamed module. That module has a dependency on all other modules and has access to the packages which they exported. It’s important that not exported packages are not accessible. Since Java 9, some APIs are marked as internal and are unavailable from regular packages. If you compile code using such packages in Java 8 and try to use it with Java 9, you’ll get a runtime error.

Message for Today

It’s time to get your hands dirty by writing your first Java 9 module. I’ve prepared the simplest example to help you start. It’s available on my GitHub: Java 9 modules - the simplest example.