Java 9 – First baby steps with Modules and jlink image 91

Java 9 – First baby steps with Modules and jlink

In a recent article, I created an isolated Docker Container as Java 9 R&D environment: In this article, I will use that environment to take few small steps with Java 9 – in particular with modules. Note:this story does not end well. I wanted to conclude with using jlink to create a stand alone runtime that contained both the required JDK modules and my own module – and demonstrate how small that runtime was. Unfortunately, the Link step failed for me. More news on that in a later article.

Create Custom Module

Start a container based on the openjdk:9 image, exposing its port 80 on the docker host machine and mapping folder /vagrant (mapped from my Windows host to the Docker Host VirtualBox Ubuntu image) to /var/www inside the container:

docker run -it -p -v /vagrant:/var/www openjdk:9 /bin/sh

Create Java application with custom module:  I create a single Module (nl.amis.j9demo) and a single class nl.amis.j9demo.MyDemo. The module depends directly on one JDK module (httpserver) and indirectly on several more.

imageThe root directory for the module has the same fully qualified name as the module: nl.amis.j9demo.

This directory contains the file. This file specifies:

  • which modules this module depends on
  • which packages it exports (for other modules to create dependencies on)

In my example, the file is very simple – only specifying a dependency on jdk.httpserver:


The Java Class MyDemo has a number of imports. Many are for base classes from the java.base module. Note: every Java module has a implicit dependency on java.base, so we do not need to include it in the file.


This code create an instance of HttpServer – an object that listens for HTTP Requests at the specified port (80 in this case) and then always returns the same response (the string “This is the response”). As meaningless as that is – the notion of receiving and replying to HTTP Requests in just few lines of Java Code (running in the OpenJDK!) is quite powerful.

package nl.amis.j9demo;
import java.util.*;
import java.util.concurrent.*;

import static java.lang.System.out;
import static*;

public class MyDemo{
  private static final int DEFAULT_PORT = 80;
  private static URI ROOT_PATH = URI.create("/"); 

private static class MyHandler implements HttpHandler {
       public void handle(HttpExchange t) throws IOException {
           URI tu = t.getRequestURI();
           InputStream is = t.getRequestBody();
           // .. read the request body
           String response = "This is the response";
           t.sendResponseHeaders(200, response.length());
           OutputStream os = t.getResponseBody();

  public static void main(String[] args) throws IOException {
    HttpServer server = HttpServer.create(new InetSocketAddress(DEFAULT_PORT), 0);
    server.createContext("/apps ", new MyHandler());
    server.setExecutor(null); // creates a default executor
    out.println("HttpServer is started, listening at port "+DEFAULT_PORT);


Compile, Build and Run

Compile the custom module:

javac -d mods –module-source-path src -m nl.amis.j9demo


Create destination directory for JAR file

mkdir -p lib

Create the JAR for the module:

jar –create –file lib/nl-amis-j9demo.jar –main-class nl.amis.j9demo.MyDemo -C mods/nl.amis.j9demo .


Inspect the JAR file:

jar tvf lib/nl-amis-j9demo.jar


To run the Java application- with a reference to the module:

java –p lib/ -m nl.amis.j9demo


the traditional equivalent with a classpath for the JAR file(s) would be:

java -classpath lib/nl-amis-j9demo.jar nl.amis.j9demo.MyDemo

Because port 80 in the container was exposed and mapped to port 8080 on the Docker Host, we can access the Java application from the Docker Host, using wget:



The response from the Java application is hardly meaningful However, the fact that we get a response at all is quite something: the ‘remote’  container based on openjdk:9 has published an HTTP server from our custom module that we can access from the Docker Host with a simple HTTP request.


I tried to use jlink – to create a special runtime for my demo app, consisting of required parts of JDK and my own module. I expect this runtime to be really small.

The JVM modules by the way on my Docker Container are in /docker-java-home/jmods


The command for this:

jlink –output mydemo-runtime –module-path lib:/docker-java-home/jmods –limit-modules nl.amis.j9demo –add-modules nl.amis.j9demo –launcher demorun=nl.amis.j9demo –compress=2 –no-header-files –strip-debug

Unfortunately, on my OpenJDK:9 Docker Image, linking failed with this error:


Error: java.nio.file.FileSystemException: mydemo-runtime/legal/jdk.httpserver/ASSEMBLY_EXCEPTION: Protocol error


Documentation for jlink –

JavaDoc for HttpServer package –

Java9 Modularity Part 1 (article on Medium by Chandrakala) –

JavaOne 2017 Keynote – Mark Reynolds demoing jlink –

Exploring Java 9 Modularity –