Java 9 Cookbook

4.7 (3 reviews total)
By Mohamed Sanaulla , Nick Samoylov
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Installation and a Sneak Peek into Java 9

About this book

Java is an object-oriented programming language. It is one of the most widely accepted languages because of its design and programming features, particularly in its promise that you can write a program once and run it anywhere.

This cookbook offers a range of software development examples in simple and straightforward Java 9 code, providing step-by-step resources and time-saving methods to help you solve data problems efficiently. Starting with the installation of Java, each recipe addresses a specific problem, with a discussion that explains the solution and offers insight into how it works.

We cover major concepts such as Project Jigsaw and various tools that will enable you to modularize your applications. You will learn new features in the form of recipes that will make your applications modular, secure, and fast.

Publication date:
August 2017
Publisher
Packt
Pages
624
ISBN
9781786461407

 

Chapter 1. Installation and a Sneak Peek into Java 9

In this chapter, we will cover the following recipes: 

  • Installing JDK 9 on Windows and setting up the PATH variable
  • Installing JDK 9 on Linux (Ubuntu, x64) and configuring the PATH variable
  • Compiling and running a Java application
  • New features in Java 9
  • Using new tools in JDK 9
  • Comparing JDK 8 with JDK 9
 

Introduction


Every quest for learning a programming language begins with setting up the environment to experiment our learning. Keeping in sync with this philosophy, in this chapter, we will show you how to set up your development environment and then run a simple modular application to test our installation. After that, we'll give you an introduction to the new features and tools in JDK 9. Then, we'll end the chapter with a comparison between the JDK 8 and JDK 9 installations.

 

Installing JDK 9 on Windows and setting up the PATH variable


In this recipe, we will look at installing JDK on Windows and how to set up the PATH variable to be able to access the Java executables (such as javac, java, and jar, among others) from anywhere within the command shell.

How to do it...

  1. Visit https://jdk9.java.net/download/ and accept the early adopter license agreement, which looks like this:

  2. After accepting the license, you will get a grid of the available JDK bundles based on the OS and architecture (32/64 bit), as shown here:

  1. Click to download the relevant JDK executable (.exe) for your Windows platform.
  2. Run the JDK executable (.exe) and follow the onscreen instructions to install JDK on your system.
  3. If you have chosen all the defaults during the installation, you will find JDK installed in C:/Program Files/Java for 64 bit and C:/Program Files (x86)/Java for 32 bit.

Now that we have finished installing JDK, let's see how we can set the PATH variable.

The tools provided with JDK, namely javac, java, jconsole, and jlink, among others, are available in the bin directory of your JDK installation. There are two ways you could run these tools from the command prompt:

  1. Navigate to the directory where the tools are installed and then run them, as follows: 
      cd "C:\Program Files\Java\jdk-9\bin"
      javac -version
  1. Export the path to the directory so that the tools are available from any directory in the command prompt. To achieve this, we have to add the path to the JDK tools in the PATH environment variable. The command prompt will search for the relevant tool in all the locations declared in the PATH environment variable. 

Let's see how you can add the JDK bin directory to the PATH variable:

  1. Right click on My Computer and then click on Properties. You will see your system information. Search for Advanced system settings and click on it to get a window, as shown in the following screenshot:

 

  1. Click on Environment Variables to view the variables defined in your system. You will see that there are quite a few environment variables already defined, as shown in the following screenshot (the variables will differ across systems; in the following screenshot, there are a few predefined variables and a few variables added by me):
    The variables defined under System variables are available across all the users of the system, and those defined under User variables for sanaulla are available only to the user, sanaulla.
  2. Click on New under User variables for <your username> to add a new variable, with the name JAVA_HOME, and its value as the location of the JDK 9 installation. For example, it would be C:/Program Files/Java/jdk-9 (for 64 bit) or C:/Program Files (x86)/Java/jdk-9 (for 32 bit):
  1. The next step is to update the PATH environment variable with the location of the bin directory of your JDK installation (defined in the JAVA_HOME environment variable). If you already see the PATH variable defined in the list, then you need to select that variable and click on Edit. If the PATH variable is not seen, then click on New.
  2. Any of the actions in the previous step will give you a popup, as shown in the following screenshot (on Windows 10):

The following image shows the other Windows versions:

  1. You can either click on New in the first picture and insert the value, %JAVA_HOME%/bin, or you can append the value against the Variable value field by adding ; %JAVA_HOME%/bin. The semicolon (;) in Windows is used to separate multiple values for a given variable name.
  2. After setting the values, open the command prompt and then run javac -version, and you should be able to see javac 9-ea as the output. If you don't see it, then it means that the bin directory of your JDK installation has not been correctly added to the PATH variable.
 

Installing JDK 9 on Linux (Ubuntu, x64) and configuring the PATH variable


In this recipe, we will look at installing JDK on Linux (Ubuntu, x64) and also how to configure the PATH variable to make the JDK tools (such as javac, java, jar, and others) available from any location within the terminal.

How to do it...

  1. Follow the Steps 1 and 2 of the Installing JDK 9 on Windows and setting up the PATH variable recipe to reach the downloads page.
  2. Copy the download link (tar.gz) for the JDK for the Linux x64 platform from the downloads page. 
  3. Download the JDK by using $> wget <copied link>, for example, $> wget http://download.java.net/java/jdk9/archive/180/binaries/jdk-9+180_linux-x64_bin.tar.gz.
  4. Once the download completes, you should have the relevant JDK available, for example, jdk-9+180_linux-x64_bin.tar.gz. You can list the contents by using $> tar -tf jdk-9+180_linux-x64_bin.tar.gz. You can even pipe it to more to paginate the output: $> tar -tf jdk-9+180_linux-x64_bin.tar.gz | more.
  5. Extract the contents of the tar.gz file under /usr/lib by using $> tar -xvzf jdk-9+180_linux-x64_bin.tar.gz -C /usr/lib. This will extract the contents into a directory, /usr/lib/jdk-9. You can then list the contents of JDK 9 by using $> ls /usr/lib/jdk-9.
  1. Update the JAVA_HOME and PATH variables by editing the .bash_aliases file in your Linux home directory: 
      $> vim ~/.bash_aliases
      export JAVA_HOME=/usr/lib/jdk-9
      export PATH=$PATH:$JAVA_HOME/bin

Source the .bashrc file to apply the new aliases:

      $> source ~/.bashrc
      $> echo $JAVA_HOME
      /usr/lib/jdk-9
      $>javac -version
      javac 9
      $> java -version
      java version "9"
      Java(TM) SE Runtime Environment (build 9+180)
      Java HotSpot(TM) 64-Bit Server VM (build 9+180, mixed mode)

Note

All the examples in this book are run against JDK installed on Linux (Ubuntu, x64), except for places where we have specifically mentioned that these are run on Windows. We have tried to provide run scripts for both platforms.The recipes on JavaFX are completely executed on Windows. 

 

Compiling and running a Java application


In this recipe, we will write a very simple modular Hello world program to test our JDK installation. This simple example prints Hello world in XML; after all it's the world of web services.

Getting ready

You should have JDK installed and the PATH variable updated to point to the JDK installation.

How to do it...

  1. Let's define the model object with the relevant properties and annotations that will be serialized into XML:
        @XmlRootElement
        @XmlAccessorType(XmlAccessType.FIELD) 
        class Messages{     
          @XmlElement 
          public final String message = "Hello World in XML"; 
        }

In the preceding code, @XmlRootElement is used to define the root tag, @XmlAccessorType is used to define the type of source for the tag name and tag values, and @XmlElement is used to identify the sources that become the tag name and tag values in the XML.

  1. Now, let's serialize an instance of the Message class into XML using JAXB:
        public class HelloWorldXml{
          public static void main(String[] args) throws JAXBException{
            JAXBContext jaxb = JAXBContext.newInstance(Messages.class);
            Marshaller marshaller = jaxb.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT,
                                   Boolean.TRUE);
            StringWriter writer = new StringWriter();
            marshaller.marshal(new Messages(), writer);
            System.out.println(writer.toString());
          } 
        }
  1. We will now create a module named com.packt. To create a module, we need to create a file named module-info.java, which contains the module definition. The module definition contains the dependencies of the module and the packages exported by the module to other modules:
        module com.packt{
          //depends on the java.xml.bind module
          requires java.xml.bind;
          //need this for Messages class to be available to java.xml.bind
          exports  com.packt to java.xml.bind;
        }

Note

We will explain modules in detail in Chapter 3, Modular Programming. But this example is just to give you a taste of modular programming and also to test your JDK installation. 

The directory structure with the preceding files is as follows:

  1. Let's now compile and run the code. From the directory, hellowordxml, create a new directory in which to place your compiled class files:
 mkdir -p mods/com.packt

Compile the source, HelloWorldXml.java and module-info.java, into the mods/com.packt directory:

      javac -d mods/com.packt/ src/com.packt/module-info.java
      src/com.packt/com/packt/HelloWorldXml.java
  1. Run the compiled code by using java --module-path mods -m com.packt/com.packt.HelloWorldXml. You will see the following output:
<messages><message>Hello World in XML</message></messages>

Do not worry if you are not able to understand the options passed with the java or javac commands. You will learn about them in Chapter 3, Modular Programming. 

 

New features in Java 9


The release of Java 9 is a milestone in the Java ecosystem. The much awaited modular framework developed under Project Jigsaw will be part of this Java SE release. Another major feature in this is the JShell tool, which is an REPL tool for Java. Apart from this, there are other important API changes and JVM-level changes to improve the performance and debuggability of the JVM. In a blog post (https://blogs.oracle.com/java/jdk-9-categories), Yolande Poirier categorizes JDK 9 features into the following: 

  1. Behind the scenes
  2. New functionality
  3. Specialized
  4. New standards
  5. Housekeeping
  6. Gone

The same blog post has summarized the preceding categorization into the following image:

In this recipe, we will discuss a few important features of JDK 9 and, wherever possible, also show a small code snippet of that feature in action. Every new feature in JDK is introduced by means of JDK Enhancement Proposals, also called JEPs. More information about the different JEPs part of JDK 9 and the release schedule of JDK 9 can be found on the official project page:http://openjdk.java.net/projects/jdk9/. 

How to do it...

We have picked a few features, which we feel are amazing and worth knowing about. In the following few sections, we'll briefly introduce you to those features.

JEP 102 -- Process API updates

Java's Process API has been quite primitive, with support only to launch new processes, redirect the processes' output, and error streams. In this release, the updates to the Process API enable the following:

  • Get the PID of the current JVM process and any other processes spawned by the JVM
  • Enumerate the processes running in the system to get information such as PID, name, and resource usage
  • Managing process trees
  • Managing sub processes

Let's look at a sample code, which prints the current PID as well as the current process information:

//NewFeatures.java
public class NewFeatures{
  public static void main(String [] args) {
    ProcessHandle currentProcess = ProcessHandle.current();
    System.out.println("PID: " + currentProcess.getPid());
    ProcessHandle.Info currentProcessInfo = currentProcess.info();
    System.out.println("Info: " + currentProcessInfo);
  }
}

JEP 110 -- HTTP/2 client

Note

This feature is being included in the incubator module. This means that the feature is expected to change in the subsequent releases and may even be removed completely. So, we advise you to use this on an experimental basis.

Java's HTTP API has been the most primitive. Developers often resort to using third-party libraries, such as Apache HTTP, RESTlet, Jersey, and so on. In addition to this, Java's HTTP API predates the HTTP/1.1 specification and is synchronous and hard to maintain. These limitations called for the need to add a new API. The new HTTP client API provides the following:

  • A simple and concise API to deal with most HTTP requests
  • Support for HTTP/2 specification
  • Better performance
  • Better security
  • A few more enhancements

Let's see a sample code to make an HTTP GET request using the new APIs. Below is the module definition defined within the file module-info.java:

//module-info.java
module newfeatures{
    requires jdk.incubator.httpclient;
}

The following code uses the HTTP Client API, which is part of jdk.incubator.httpclient module:

 

import jdk.incubator.http.*;
import java.net.URI;
public class Http2Feature{
  public static void main(String[] args) throws Exception{ 
    HttpClient client = HttpClient.newBuilder().build();
    HttpRequest request = HttpRequest
      .newBuilder(new URI("http://httpbin.org/get"))
      .GET()
      .version(HttpClient.Version.HTTP_1_1)
      .build();
    HttpResponse<String> response = client.send(request, 
      HttpResponse.BodyHandler.asString());
    System.out.println("Status code: " + response.statusCode());
    System.out.println("Response Body: " + response.body()); 
  }
}

JEP 213 -- milling project coin

In Java SE 7, _ were introduced as part of the numbers, whereby a large number could be conveniently written by introducing _ between the digits. This helped in increasing the readability of the number, for example:

Integer large_Number = 123_123_123; 
System.out.println(large_Number); 

In Java SE 8, the use of _ in the variable names, as shown earlier, resulted in a warning, but in Java SE 9, this use results in an error, which means that the variables can no longer have _ in their names.

The other changed part of this JEP is to support private methods in interfaces. Java started with interfaces with absolutely no method implementations. Then, Java SE 8 introduced default methods that allowed interfaces to have methods with implementations, called default methods. So any class implementing this interface could choose not to override the default methods and use the implementation provided in the interface.

Java SE 9 is introducing private methods, wherein the default methods in the interfaces can share code between them by refactoring the common code into private methods. 

Another useful feature is the allowing of effectively final variables to be used with try-with-resources. As of Java SE 8, we needed to declare a variable within the try-with-resources block, such as the following: 

try(Connection conn = getConnection()){}catch(Exception ex){}. 

However, with Java SE 9, we can do the following: 

try(conn){}catch(Exception ex){} 

Here, conn is effectively final; that is, it has been declared and defined before, and will never be reassigned during out the course of the program execution.

JEP 222: jshell -- the Java shell (Read-Eval-Print Loop)

You must have seen languages, such as Ruby, Scala, Groovy, Clojure, and others shipping with a tool, which is often called REPL (Read-Eval-Print-Loop). This REPL tool is extremely useful in trying out the language features. For example, in Scala, we can write a simple Hello World program as scala> println("Hello World");

Some of the advantages of the JShell REPL are as follows:

  • Help language learners to quickly try out the language features
  • Help experienced developers to quickly prototype and experiment before adopting it in their main code base
  • Java developers can now boast of an REPL

Let's quickly spawn our command prompts/terminals and run the JShell command, as shown in the following image:

There is a lot more we can do, but we will keep that for Chapter 13, The Read-Evaluate-Print Loop (REPL) Using JShell.

JEP 238 -- multi-release JAR files

As of now, JAR files can contain classes that can only run on the Java version they were compiled for. To leverage the new features of the Java platform on newer versions, the library developers have to release a newer version of their library. Soon, there will be multiple versions of the library being maintained by the developers, which can be a nightmare. To overcome this limitation, the new feature of multirelease JAR files allows developers to build JAR files with different versions of class files for different Java versions. The following example makes it more clear. 

Here is an illustration of the current JAR files:

jar root
  - A.class
  - B.class
  - C.class

Here is how multirelease JAR files look:

jar root
  - A.class
  - B.class
  - C.class
  - META-INF
    - versions 
      - 9
        - A.class
      - 10
        - B.class

In the preceding illustration, the JAR files support class files for two Java versions--9 and 10. So, when the earlier JAR is executed on Java 9, the A.class under the versions- 9 folder is picked for execution. On a platform that doesn't support multirelease JAR files, the classes under the versions directory are never used. So, if you run the multirelease JAR file on Java 8, it's as good as running a simple JAR file.

JEP 266 -- more concurrency updates

In this update, a new class, java.util.concurrent.Flow, has been introduced, which has nested interfaces supporting the implementation of a publish-subscribe framework. The publish-subscribe framework enables developers to build components that can asynchronously consume a live stream of data by setting up publishers that produce the data and subscribers that consume the data via subscription, which manages them. The four new interfaces are as follows:

  • java.util.concurrent.Flow.Publisher
  • java.util.concurrent.Flow.Subscriber
  • java.util.concurrent.Flow.Subscription
  • java.util.concurrent.Flow.Processor (which acts as both Publisher and Subscriber).

Project Jigsaw

The main aim of this project is to introduce the concept of modularity; support for creating modules in Java and then apply the same to the JDK; that is, modularize the JDK. Some of the benefits of modularity are as follows:

  • Stronger encapsulation: The modules can access only those parts of the module that have been made available for use. So, the public classes in a package are not public unless the package is explicitly exported in the module info file. This encapsulation cannot be broken by using reflection (except in cases where the module is an open module or specific packages in the module have been made open).
  • Clear dependencies: Modules must declare which other modules they would be using via the requires clause.
  • Combining modules to create a smaller runtime, which can be easily scaled to smaller computing devices.
  • Make the applications more reliable by eliminating runtime errors. For example, you must have experienced your application failing during runtime due to missing classes, resulting in ClassNotFoundException.

There are various JEPs, which are part of this project, as follows:

  • JEP 200 - modular JDK: This applies the Java platform module system to modularize the JDK  into a set of modules that can be combined at compile time, build time, or runtime.
  • JEP 201 - modular source code: This modularizes the JDK source code into modules and enhances the build tools to compile the modules.
  • JEP 220 - modular runtime images: This restructures the JDK and JRE runtime images to accommodate modules and to improve performance, security, and maintainability.
  • JEP 260 - encapsulate most internal APIs: This allows a lot of internal APIs to be accessed directly or via reflection. Accessing internal APIs that are bound to change is quite risky. To prevent its use, they are being encapsulated into modules and only those internal APIs that are widely used are being made available until a proper API is in its place.
  • JEP 261 - module system: This implements the module system Java specification by changing the Java programming language, JVM, and other standard APIs (http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html). This includes the introduction of a new construct called module, { }, with its supported keywords, such as requires, exports, opens, and uses. 
  • JEP 282: jlink, the Java linker: This allows packaging modules and their dependencies into smaller run times. 

More details about Project Jigsaw can be found from the Project Jigsaw homepage (http://openjdk.java.net/projects/jigsaw/).

There's more...

There are quite a few features listed that are significant for developers, and we thought of grouping them together for your benefit:

  • Enhance the Javadoc tool to generate HTML 5 output and the generated Javadoc should support the local search for classes and other elements. 
  • Make G1 as the default garbage collector and remove GC combinations that have been deprecated in Java 8. G1 is the new garbage collector (which has been in existence since Java SE 7), which focuses on reducing the pause times of the garbage collection activity. These pause times are very critical to latency-critical applications and, hence, such applications are going towards adopting the new garbage collector.
  • Changing the internal representation of String to make use of a byte array rather than a character array. In a character array, each array element is 2 bytes, and it was observed that a majority of strings use 1 byte. This resulted in wasteful allocation. The new representation would also introduce a flag to indicate the type of encoding used. 
  • The new stackwalking API to support navigating the stack trace, which will help to do much more than just print the stack trace.
  • Allow the image I/O plugin to support the TIFF image format.
 

Using new tools in JDK 9


There are a few new command-line tools introduced in JDK 9 to support new features. We will give you a quick overview of these tools and the same will be explained with recipes of their own in the later chapters.

Getting ready

You should have JDK 9 installed and the PATH environment variable updated to add the path to the bin directory of your JDK installation. Also, you need to have tried out HelloWorldXml explained in the recipe, Compiling and running a Java application.

How to do it...

We will look at a few interesting new command-line tools introduced.

jdeprscan

This tool is used for scanning the usage of deprecated APIs in a given JAR file, classpath, or source directory. Suppose we have a simple class that makes use of the deprecated method, addItem, of the java.awt.List class, as follows:

import java.awt.List;
public class Test{
  public static void main(String[] args){
    List list = new List();
    list.addItem("Hello");
  }
}

Compile the preceding class and then use jdeprscan, as follows:

C:Program FilesJavajdk-9bin>jdeprscan.exe -cp . Test

You will notice that this tool prints out class Test uses method java/awt/List addItem (Ljava/lang/String;)V deprecated, which is exactly what we expected.

jdeps

This tool analyses your code base specified by the path to the .class file, directory, or JAR, lists the package-wise dependency of your application, and also lists the JDK module in which the package exists. This helps in identifying the JDK modules that the application depends on and is the first step in migrating to modular applications.

We can run the tool on our HelloWorldXml example written earlier and see what jdeps provides:

$> jdeps mods/com.packt/
com.packt -> java.base
com.packt -> java.xml.bind
com.packt -> java.io                          java.base
com.packt -> java.lang                        java.base
com.packt -> javax.xml.bind                   java.xml.bind
com.packt -> javax.xml.bind.annotation        java.xml.bind

jlink

This tool is used to select modules and create a smaller runtime image with the selected modules. For example, we can create a runtime image by adding the com.packt modules created in our HelloWorldXml example:

$> jlink --module-path mods/:$JAVA_HOME/jmods/ --add-modules com.packt --output img

Looking at the contents of the img folder, we should find that it has the bin, conf, include, and lib directories. We will learn more about jlink under Chapter 3, Modular Programming.

jmod

JMOD is a new format for packaging your modules. This format allows including native code, configuration files, and other data that do not fit into JAR files. The JDK modules have been packaged as JMOD files.

The jmod command-line tool allows create, list, describe, and hash JMOD files:

  • create: This is used to create a new jmod file
  • list:  This is used to list the contents of a jmod file
  • describe: This is used to describe module details
  • hash: This is used to record hashes of tied modules

JShell

This tool has been briefly explained earlier, under the title, JEP 222: jshell - the Java shell (Read-Eval-Print Loop)

 

Comparing JDK 8 and JDK 9


Due to the application of a modular system to JDK under Project Jigsaw, there have been a few changes in the JDK directory structure installed in your systems. In addition to these, there were a few changes undertaken to fix the JDK installation structure, which dates back to the times of Java 1.2. This has been deemed to be a golden opportunity by the JDK team to fix the issues with the JDK directory structure.

Getting ready

To see the difference in the JDK 9 directory structure, you will need to install a pre-JDK 9 version. We have chosen to use JDK 8 to compare with JDK 9. So, go ahead and install JDK 8 before you proceed further. 

How to do it...

  1. We did a side-by-side comparison of both the JDK installation directories as shown in the following:
  1. Following are our observations from the preceding comparison:
    • The jre directory has been completely removed and has been replaced by jmods and conf. The jmods directory contains the runtime images of the JDK modules, the conf directory contains configuration and property files, which were earlier under the jre directory. 
    • The contents of jrebin and jrelib have been moved to the lib and bin directories of JDK installation.

See also

Refer to the following recipe of this chapter:

  • Using new tools in JDK 9

About the Authors

  • Mohamed Sanaulla

    Mohamed Sanaulla is a full-stack developer with more than 8 years, experience in developing enterprise applications and Java-based backend solutions for e-commerce applications.

    His interests include enterprise software development, refactoring and redesigning applications, designing and implementing RESTful web services, troubleshooting Java applications for performance issues, and TDD.

    He has strong expertise in Java-based application development, ADF (a JSF-based Java EE web framework), SQL, PL/SQL, JUnit, designing RESTful services, Spring, Spring Boot, Struts, Elasticsearch, and MongoDB. He is also a Sun Certified Java Programmer for the Java 6 platform. He is a moderator for JavaRanch and likes to share his findings on his blog.

    Browse publications by this author
  • Nick Samoylov

    Nick Samoylov graduated from the Moscow Institute of Physics and Technology, has worked as a theoretical physicist, and learned to program as a tool for testing his mathematical models. Following the demise of the USSR, Nick created and successfully ran his own software company. In 1999, with his wife Luda and two daughters, he emigrated to the USA and has been living in Colorado ever since, working as a Java programmer. In his spare time, Nick likes to write and hike in the Rocky Mountains.

    Browse publications by this author

Latest Reviews

(3 reviews total)
Concise and exact information.
Very well written and structured, complete, sample source code provided
So far cooking up a storm, java 9 style..

Recommended For You

Java Coding Problems

Develop your coding skills by exploring Java concepts and techniques such as Strings, Objects and Types, Data Structures and Algorithms, Concurrency, and Functional programming

By Anghel Leonard
Java 11 and 12 - New Features

Enhance your development skills with Java's state-of-the-art features and projects to make your applications leaner and faster

By Mala Gupta
Java 11 Cookbook - Second Edition

Solutions for modular, functional, reactive, GUI, network, and multithreaded programming

By Nick Samoylov and 1 more