JavaOne 2017 - Java 9, Jigsaw, Java EE 8 & EE4J

20 minute read

JavaOne took place from October 1st to 5th in San Francisco and we were there! This is the first part of our feedback about the main topics: Java 9, Jigsaw - the new Java module system, Java EE 8 and its tranformation to EE4J.

This is the first article of a series and will be followed by others, concerning different topics discussed during this edition such as micro-services, functional and reactive programming, DevOps & Serverless but also more personal feedback.

Java 9 & Jigsaw

2017 was the release year of the sooooo long awaited Java 9 that came with Jigsaw, a totaly new module system but also with many other changes.

Java 9 changes

Moving Java Forward faster

As explained by Mark Reinhold, Chief Architect of the Java Platform Group at Oracle in the post Moving Java Forward faster he wrote before JavaOne, Oracle is dramatically accelerating the release cycle of Java SE with one release every 6 months.

Java SE release number scheme is also moving from a standard scheme based on incremented numbers to a new time-based scheme:

To make it clear that these are time-based releases, and to make it easy to figure out the release date of any particular release, the version strings of feature releases will be of the form $YEAR.$MONTH. Thus next year’s March release will be 18.3, and the September long-term support release will be 18.9.

Next Java version will then be 18.3 and the next one 18.9. (or maybe not)

This new 6 months release cycle will allow Java to deliver new features in Java as soon as they are ready and only when they are ready. This requires, quoting Mark Reinhold, a new “pipeline of features that we are working on” and that could be included, as soon as they are ready, in the next jdk. This pipeline takes place in the OpenJDK community inside projects such as Panama, Valhalla, Amber or the new Loom, presented by Brian Goetz.

OpenJDK projects

edit: it seems that we could get a Java 10 version after all

Java SE Support

Oracle has also completely revised its policy regarding the support for Java SE itself and the place of OpenJDK. Starting from now, there will no longer be any difference between OracleJDK and OpenJDK!

This announcement was obviously very well received by the community but should not make us forget that it is accompanied by some significant changes regarding the support of OpenJDK & OracleJDK.

Oracle will support and patch only the last version of OpenJDK and you will have to either update your JVMs every 6 months or subscribe to OracleJDK (and pay) to beneficiate from security or performance patches. Indeed, only OracleJDK will provide LTS, not OpenJDK.

A consequence of all of this is that Java 9 is not a LTS release and will be only supported until March 2018. Prepare to upgrade quickly to 18.9 that will be the first LTS release post Java 9 and will mark the end of Oracle JDK 8 public updates. Then, there will be an Oracle LTS release every 3 years.

Jigsaw: Java modules

Jigsaw, the new Java module system was of course the most important and eagerly awaited novelty of Java 9, after repeated postponements.

It is therefore natural that many talks were about the modularization of Java itself, of our own applications and about the progressive transition to modular architectures and the impact on our day to day work. There were even some feedbacks and guidelines from early adopters such as Netflix.

Why modules?

The Jigsaw project, which is now part of Java since Java 9, aims to improve the modularity, efficiency and security of the platform, thus offering the possibility to build more scalable, lighter Java applications with a higher level of safety and security.

The ultimate ambition is to develop a complete ecosystem based on the language and the JVM. Through a modular SDK for building modular applications and using tools that are already almost compatible with this new approach.

Modular development

More concretely, Jigsaw intends to address the following points:

  • Getting rid of JAR hell / classpath hell:

    The fact that dependencies between packages are not explicitly defined leads to many problems and errors: JAR not found and NoClassDefFoundError, version conflicts and shadowing of classes and packages… not to mention transitive dependencies. Class loading mechanisms have contributed to build a complex system, poorly effective and hard to understand.

  • Stronger encapsulation & better security accross packages:

    Mechanisms of encapsulation accross packages are weak and, by means of the reflection API, they are very easy to bypass.

  • Better performances & optimized weight:

    The linear scanning of the classpath but also the “all-in-one” approach of the JDK led to poor startup performances and to an excessive application weight.

Modular JDK

The first step has been to work on the modularization of the JDK itself.

Programs are Classes Packages Modules

It has been broken down into multiple modules and each module explicitely define its dependencies to other modules … until java.base.

Modularization of Java

The fact that this new module graph defines the different components of the JDK in the form of an explicit dependency tree makes loading classes from the classpath - which has become modulepath much more efficient in localization of classes.

The new notion of layers allows to deal with class loader hierarchy in a much more intuitive manner. A minimal boot layer is now created by the JVM and results in a much better startup performance. Additional layers can be created and stacked on the top of the boot layer.

The division into modules allows to finally get rid of the monolith rt.jar and its 53Mo! Deprecated Java EE modules (such as java.corba or java.transaction) have been deprectated for removal and must be added via jlink --add-modules if needed.

This new tool, jlink allows you to finely choose the modules and dependencies to include in your distribution (including those of the SDK) and to link them together. It greatly contributes to reduce and control the size of your deployments. jlink, via the notion of link time also allows an advanced control of linking, with the possibility to choose between static linking and dynamic linking.

$ jlink --module-path <modulepath> --add-modules <modules> --limit-modules <modules> --output <path>

All this helps to offer a much more lighter JDK to embed in our applications.

jdeps, the Java Dependency Analysis Tool, is a new command line tool that analyzes the dependencies between classes and offers a great help in the modularization process.

jdeps

Using modules

A module remains a regular JAR file with a module-info.class file at its root containing its name and its dependencies.

As usual, naming is essential and hard and the strategy will depend on the nature of the module: application or library.

Module naming

Dependencies are expressed using requires, exports keyword.

requires, requires transitive and requires static allow declaring direct, transitive or even static dependencies. Static dependencies make possible expression of optional dependencies, declaring that a dependency is mandatory at compile time but not necessarily available at run time: the application will be able to start without that dependency.

Even public types of a module are no more visible outside of itself. To make them visible by other modules, you’ll have to explicitely export packages with the exports keyword. Note that you can explicitely restrain the visibility to some modules using exports <package> to <module>.

Module primer

To enforce security, you cannot anymore use reflection without permissions on private fields. No more setAccessible(true) ;-)! Required modules have to explicitely allow it using the opens keyword on a given package to allow its usage or use open <module-name> when declaring the module to allow usage for the entire module.

exports and opens have considerably increased the safety and encapsulation of the modules, at compile time and at runtime. And deep reflection is not a free lunch anymore.

Module primer

The ServiceLoader mechanism, that exists since Java 6 but was never really exploited, has been revamped. Indeed, using requires and exports enforce encapsulation but in case of multiple possible implementations, you cannot rely only on interfaces and still have to create concrete instances yourself which leads to excessive coupling. Services claim to address this concern by registering implementations on one side and relying on the ServiceLocator on the other to retreive concrete objects.

A module can declare a service by using provides <interface> with <implementation>, then becoming a Service provider. To use a service provided by another module, a Service consumer module has to declare uses <interface> inside its module-info.jar, in addition to requiring the module itself.

Modules services usage

Migration path & backward compatibility

To facilitate the migration and its adoption, Jigsaw is announced as taking into consideration the backward compatibility of existing applications, if they complied with previous standards.

Several mechanisms are available for this purpose:

  • class-path & unnamed modules: Classpath did not completely disappear and you can simply load your legacy pre-Java 9 libraries using the command line and the --class-path option. All these libs and packages will then be added to a unique unnamed module. All packages inside this module will have full access to other internal packages, to any public exported package of the module-path and any module from the module-path will have access to public classes from packages of the unnamed module. But it seems that this is is a short-term situation to facilitate migration and strong encapsulation is the target for future OpenJDK releases. It means that that classes from the unnamed module (in fact the classpath) will not export anything.

  • To go one step further, you can start considering you legacy JARs as quite regular modules inside the module-path. Each JAR will then be considered as an automatic module real module which name will be deducted from the JAR file name without version, extension, etc. If needed, the automatic name of your JAR file can be customized with Automatic-Module-Name in the MANIFEST.MF.

  • jlink options --add-modules and --add-opens allow to keep deprecated modules and to authorize again Illegal access to JDK internals.

Tools and frameworks have already done a great job in supporting Java 9 and modules and most of them are already provinding a good support of these new features and architecture

Migrating to Java 9

Challenges

That was theory! In practice, it will still lead to many challenges:

As mentionned above, naming of modules will be non trivial with strong unicity constraints and requirements. Automatic modules without explicit Automatic-Module-Name could lead to ambiguous situations, conflicts and errors. This point may be particularly painful during the transition period, until the entire ecosystem has migrated to the modules.

Jigsaw also considers the versionning is not his area of responsibility and leaves this problem to build tools. It does not offer any mechanism to manage or even declare the version of modules.

This point seems particularly problematic to me and I confess to be rather skeptical about the possibility of concretely managing direct and transitive dependencies of an entire application without structurally taking into account versions and possible collisions.

But becoming modular is not just a matter of backward compatibility. We will have to rethink part of our architectures and significantly refactor our applications to take into account these new patterns. No more overloading of packages, for example:

Traditional architecture

Modular architecture

Deciding on the granularity of the modules will also be very challenging, between small modules promoting composability and reusability and all-in-one modules that will be much easier to implement. One answer might be not to choose and to use aggregator modules requiring all necessary dependencies to multiple small modules.

Modules aggregator

Another important drawback of the modularization is code testing. A few sessions were about build tools and keeping the tests working. The main problem is that test code can not access main source code if it is compiled in two modules. Cédric Champeau provided some insights on how Gradle tackles the problem and it is merely a hack today (hack java compiler task to give it the classpath as module path). Even though, Gradle gives a workaround to this problem, the question remains on the plugins and extensions used by build tools. There is a huge number of plugins not yet compatible with Java 9, breaking builds so there is still lots of work before having projects building correctly on Java 9.

Conclusion

The arrival of Jigsaw is certainly an important step in the modernization of the platform but does not necessarily convince everyone on all the aspects it intends to deal with.

Modernization of the classpath, class loading, modularization of the JDK and the resulting improvements in performance and efficiency are certainly important steps.

Given the increase in complexity caused by modules, however, this was not enough to significantly reduce the overall complexity of these mechanisms, and the absence of versioning in dependency management is still an important source of questioning.

After so many years of waiting, we are legitimate to wonder if this proposal addresses all the necessary problems and will be able to obtain the community’s agreement. Some reservations were publicly expressed by two members of the JCP: IBM and RedHat.

The next few months will be critical and it will be interesting to observe the degree of adoption within the entire ecosystem and community involvement in the migration of tools, applications, frameworks and libraries.

Talks

Other Java 9 features

With Jigsaw, modularity is obviously the biggest change in Java 9, but this new release came with many other improvements and features regarding tooling, performances, APIs, security or even language.

Tools

  • jshell: a REPL (Read Eval Print Loop) for Java: Java finally has a command line and its name is jshell (or JEP 222).

    Like any command line tool, jshell provides Tab completion, retrieves information from javadoc, etc. It can be used as a binary tool but also via its API.

Jshell

But, as pointed out by Simon Mapple and Oleg Shelajev in their very funny talk The Good Cop/Bad Cop Guide to Java 9, jshell comes with new behaviors, quite unusual in the Java world:

You can download the JShell user guide

  • JavaDoc.Next - a new generation of JavaDoc: Rejuvenation cure for JavaDoc with JavaDoc.Next with HTML5 support and doclint support, a simplified Doclet API and a quite powerfull JavaDoc search box by default!

  • Compiling: With Multi release jar files (JEP 238) you can build a single jar file containing multiple Java-release-specific versions of a class/resource file, with Compile for Older Platform Versions (JEP 247) you can compile for older releases.

    Multi release jar files

Language

API improvements

  • Strings and string concatenation: Replacement of String-internal char[] representation with a byte[] array plus encoding field thanks to Compact Strings (JEP 254), optimization of String concatenation with Indify String Concatenation (JEP 280)

  • Initializing collections with of method: Convenience Factory Methods for Collections (JEP 269) is offering a far more elegant solution for initializing collections:

    // Java 8
    Set<String> set =
      Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "b", "c")));
      
    // Java 9
    Set<String> set = Set.of("a", "b", "c");
    
  • New methods in java.util.Objects:

    java.util.objects

Security enhancements

Not to mention security enhancements coming with Java 9 and presented by Sean Mullan in his talk “Making the JDK more secure” (slides).

Making the JDK more secure

We are not going to go into detail here on this topic but you’ll find everything in this talk and on this dedicated guide to Secure coding guidelines for Java SE, updated for Java 9.

A new Cryptographic Roadmap has also been published.

JVM & Performances

Many improvements have been made on the JVM regarding performances, garbage collector, vectorization, etc. We are not going to list them all here, but if you are interested, you should take a look to Mikael Vidstedt and Sandhya Viswanathan’s talk JDK 9 Hidden Gems (slides).

Talks

Java EE to EE4J

2017 has not only been a pivotal year for Java SE, it is also a year of radical transformation for Java EE. As announced prior to JavaOne, Oracle is “opening up” Java EE to the community.

Java EE is already developed in open source so it is not about opening the code itself but about transferring the governance of Java EE to the community.

… the process is not seen as being agile, flexible or open enough, particularly when compared to other open source communities. We’d like to do better.

In practice, it is the Eclipse foundation that will have the heavy task of hosting the Java EE galaxy and taking charge of its governance with Redhat, IBM, Tomitribe, etc. as the main actors. Future versions of Java EE, with EE4J as new name, will be licenced under Eclipse Public License 2.0.

Oracle assures that it will continue to play a major role in the evolution of Java EE without going into further detail and many questions remain unresolved regarding Oracle’s participation in JCP, TCKs, etc.

We will continue to participate in the future evolution of Java EE technologies. But we believe a more open process, that is not dependent on a single vendor as platform lead, will encourage greater participation and innovation, and will be in best interests of the community.

The announcement was generally received positively by the community and its major actors but caused a lot of ink and saliva to flow and naturally gave rise to many debates and talks at JavaOne. With, in particular, two panels:

The main message was very optimistic: “The future of Java EE is full of promise and it’s in your hands! Participate, get involved! Contibute to the specs, contribute to the code”

Naming was one of the hard points and made a lot of noise. As usual with Oracle, there were many legal constraints on the choice of name and it was not possible, for example, to keep a name starting with Java. The name chosen for the project is officialy EE4J but it is not certain that it will remain as a brand name.

There is already very heated discussions to obtain the permission from Oracle to keep package names starting with javax.* We must admit that it would not be very intuitive to have interfaces in org.eclipse.*

These panels also took the opportunity to appeal to all companies using Java EE by inviting them to seize this opportunity and to dedicate teams to contribute to the specification and development of future versions.

Few answers, finally, after all these debates and still many open questions:

  • Will an open and collaborative community be able to provide sufficient leadership?
  • Will the key players in this community be able to agree on a shared leadership?
  • How big will Oracle’s involvement in the future of Java EE be?
  • What will be the final name?

We are not particularly Java EE guys here but we will follow carefully the next months that should be critical for the future of Java EE.

Java EE 8

Again, we are not particularily Java EE guys and we are not going to detail all the content of Java EE 8 here.

Java EE8

But we can quote:

  • New projects:
    • JSON-B: A new JSON Binding API for a much more easy conversion between Java objects from/to JSON messages. The API seems quite straightforward to use (fromJson, toJson methods…) and allows the implementation of a custom mapping via annotations such as JsonbNillable, JsonbProperty, JsonbPropertyOrder, JsonbTransient, JsonbNumberFormat, etc.
    • The new Security API whose main objective is to significantly improve portability accross servlet containers from a security management point of view. HttpAuthenticationMechanism, IdentityStore, SecurityContext will help to address these concerns.
  • Major updates for:
    • Servlet 4.0 with PushBuilder and HTTP/2 server push, etc.
    • BeanValidation 2.0 with validation of Date and Time and Optionals, cascading validation, etc.
    • CDI 2.0 with Observers, priority and asynchronous events.
  • Minor updates for:
    • JAX-RS 2.1 with a new reactive client API and server-sent events.
    • JSF 2.3 with server push.
    • JSON-P 1.1 with support of JSON Pointer, JSON Patch, and JSON Merge Patch.

The two talks below will give you the big picture:

And here is a list of more JavaOne talks about Java EE and some specific parts of the Java EE 8 release:

Conclusion

2017 was thus a year full of changes for Java. On the JDK side, many evolutions are still expected in the ecosystem and in the Java community because of the transition to the new modules system and because of the new release rythm which is much more intense. On the Java EE side, it is an even more radical change which is coming. Let’s bet that the next few months and years will be rich in evolutions and transformations, which is, after all, a good thing for the platform as a whole.

But, obviously, many other topics were also discussed during this edition 2017: micro-services, functional programming, DevOps, serverless, etc. We will talk about it in new articles to come. Stay tuned!

Java EE8


Written by

Baptiste Meurant

Software craftsman, developer, architect, unit technical director at Worldline. #java #javascript #emberjs #devops

Julien Ripault

Architect, Java addict, Guitar lover & music addict