Link phase optimizations and jlink plugins

There have always been two steps to get Java code to execute--the compile step (using javac) and the execution step (using java). During the compilation step, javac doesn't just try to convert Java code into byte code, it also tries to perform any optimizations it can and generate the most optimal and efficient byte code possible. Over the years, the Java compiler has learned several new tricks and strategies to better optimize the resulting byte code. But there has always been a challenge--the compiler works on a handful of classes at a time and it doesn't have the opportunity to see the big picture by looking at the entire application, which could have helped it implement better optimizations. That option is available for runtime, but some of the optimizations end up being too expensive when done at runtime. With the introduction of the new linking step in between the compile and execution phases, an opportunity opens up to do application-level optimization for our Java byte code. In fact, one of the goals of the platform team for the linking phase is to do whole-world optimizations--optimizations that span multiple classes and modules across the application, having been given the bigger picture.

Remember that the linking step is optional, of course. We've executed our application in the previous chapters without having to use jlink, and thereby without doing any such optimizations. However, if you were to use jlink, there's an opportunity to do optimizations--things such as compressing the image, identifying and removing unreachable code and types, pre-optimizing code, and methods where the possible inputs are constant and known ahead of time. These optimizations can happen when running jlink and are done using a series of transformers, which are built as plugins.

Here's an approximation of how jlink works to create the runtime image:

The process starts with gathering all the necessary resources and running them through a series of transformers that can do various tasks and optimizations. The jlink tool has a plugin API so that anyone can create custom plugins that hook into this process and have the opportunity to transform the resulting image. After the transformers are done, the image is written to the output directory, where, again, plugins can be written to control what happens.

The Java 9 platform comes with built-in plugins that do several of these optimizations. In fact, some of these optimizations are so important and have such a significant impact that they have been turned on by default! It's important to know some of these options that are available to you while you generate your runtime image:

  • Module descriptor optimizations with the system-modules plugin: During the initial development of modules in Java, it was noticed that the Java runtime ended up spending a significant amount of time and resources examining, parsing, and validating the module descriptors (module-info.class) of each module in the system image. Since the set of modules that are going to be bundled in an image is known at link time, the process of scanning and validating all the module descriptors can be done at link time too. There is a jlink plugin that does this bundled with the platform, and is called system-modules. This plugin generates a pre-processed and pre-validated system module graph so that the runtime doesn't have to. The process results in such significant gains in performance that it's enabled by default whenever you run jlink.
  • Compressing the image with the compress plugin: This plugin allows you to apply compression to the generated image to reduce the size of the output runtime image. There are two types of compression that this plugin can perform on the generated image. The first identifies all usages of UTF-8 strings and generates a global string table so that any common String values have to be stored only once and can be reused across the application. The second type of compression is the ZIP compression of files in the resulting image to shrink its overall size.

Unlike system-modules, this plugin is not enabled by default. To use it, you'll need to pass the --compress option to jlink. You can pass three values--0, which means no compression, 1, which enables string sharing, and 2, which does ZIP compression.

Running the two levels of compression while generating the address book image on our sample code shows the gains in size of the generated images:

      $ $JAVA_HOME/bin/jlink --module-path $JAVA_HOME/jmods:out 
--add-modules packt.addressbook.ui --bind-services
--compress=1 --output image1

$ $JAVA_HOME/bin/jlink --module-path $JAVA_HOME/jmods:out
--add-modules packt.addressbook.ui --bind-services
--compress=2 --output image2

Examining the sizes of the resulting images shows us how much space the compression has saved us. The following table summarizes the folder sizes on my machine after running these commands:

Compression

Address book image size

None

167.5 MB

Level 1

129.4 MB

Level 2

95.9 MB

  • Locale information with the include-locales plugin: By default, the runtime image bundles in all installed locale information. If you are targeting your application runtime only for certain locales, you can use the --include-locales option and pass the comma-separated list of locales you need. Only those locales will be included in the resulting image, thus freeing up more space:
      $ $JAVA_HOME/bin/jlink --module-path $JAVA_HOME/jmods:out
--add-modules packt.addressbook.ui --bind-services
--compress=2 --include-locales=en --output image3

The preceding command regenerates the image with full compression, and with the English locale included (--include-locales=en). On my machine, this resulted in further space savings, with the image size at 88.2 MB.

There are several other handy plugins that come bundled in the JDK. To get to know what plugins are available, and to learn how to use them, you can run jlink with the --list-plugins option. The complete list of installed plugins will be displayed, including the plugins we've just learned about and much more:

$ $JAVA_HOME/bin/jlink --list-plugins
..................Content has been hidden....................

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