Sunday 16 June 2019

Java9: jlink: Linking Modules


jlink tool is used to assemble and optimize a set of modules and their dependencies into a custom runtime image. ‘jlink’ tool comes as part of java 9 installation.

Open command prompt or terminal and execute ‘jlink --help' command to get help of all jlink commands.
$jlink --help
Usage: jlink <options> --module-path <modulepath> --add-modules <module>[,<module>...]
Possible options include:
      --add-modules <mod>[,<mod>...]    Root modules to resolve
      --bind-services                   Link in service provider modules and
                                        their dependences
  -c, --compress=<0|1|2>                Enable compression of resources:
                                          Level 0: No compression
                                          Level 1: Constant string sharing
                                          Level 2: ZIP
      --disable-plugin <pluginname>     Disable the plugin mentioned
      --endian <little|big>             Byte order of generated jimage
                                        (default:native)
  -h, --help, -?                        Print this help message
      --ignore-signing-information      Suppress a fatal error when signed
                                        modular JARs are linked in the image.
                                        The signature related files of the
                                        signed modular JARs are not copied to
                                        the runtime image.
      --launcher <name>=<module>[/<mainclass>]
                                        Add a launcher command of the given
                                        name for the module and the main class
                                        if specified  
      --limit-modules <mod>[,<mod>...]  Limit the universe of observable
                                        modules
      --list-plugins                    List available plugins
  -p, --module-path <path>              Module path
      --no-header-files                 Exclude include header files
      --no-man-pages                    Exclude man pages
      --output <path>                   Location of output path
      --post-process-path <imagefile>   Post process an existing image
      --resources-last-sorter <name>    The last plugin allowed to sort
                                        resources
      --save-opts <filename>            Save jlink options in the given file
  -G, --strip-debug                     Strip debug information
      --suggest-providers [<name>,...]  Suggest providers that implement the
                                        given service types from the module path
  -v, --verbose                         Enable verbose tracing
      --version                         Version information
      @<filename>                       Read options from file

How to build an image using jlink tool?
I am going to use ‘services_example’ application that I created in my previous post to build an image. I would recommend you to go through my previous post and build ‘services_example’ application.


‘service_example’ project structure looks like below.
$tree service_example/
service_example/
└── src
    ├── app.interfaces
    │   ├── com
    │   │   └── sample
    │   │       └── app
    │   │           └── interfaces
    │   │               └── Circle.java
    │   └── module-info.java
    ├── app.interfaces.impl
    │   ├── com
    │   │   └── sample
    │   │       └── app
    │   │           └── interfaces
    │   │               └── impl
    │   │                   └── CircleImpl.java
    │   └── module-info.java
    ├── app.interfaces.otherimpl
    │   ├── com
    │   │   └── sample
    │   │       └── app
    │   │           └── interfaces
    │   │               └── otherimpl
    │   │                   └── CircleImpl.java
    │   └── module-info.java
    └── app.main
        ├── com
        │   └── sample
        │       └── app
        │           └── App.java
        └── module-info.java

22 directories, 8 files

Step 1: Go to ‘service_example’ directory. Compile App.java and CircleImpl.java files by executing below commands.

javac --module-source-path src -d out src/app.main/com/sample/app/App.java

javac --module-source-path src -d out src/app.interfaces.impl/com/sample/app/interfaces/impl/CircleImpl.java

javac --module-source-path src -d out src/app.interfaces.otherimpl/com/sample/app/interfaces/otherimpl/CircleImpl.java


Total project structure looks like below.
$tree
.
├── out
│   ├── app.interfaces
│   │   ├── com
│   │   │   └── sample
│   │   │       └── app
│   │   │           └── interfaces
│   │   │               └── Circle.class
│   │   └── module-info.class
│   ├── app.interfaces.impl
│   │   ├── com
│   │   │   └── sample
│   │   │       └── app
│   │   │           └── interfaces
│   │   │               └── impl
│   │   │                   └── CircleImpl.class
│   │   └── module-info.class
│   ├── app.interfaces.otherimpl
│   │   ├── com
│   │   │   └── sample
│   │   │       └── app
│   │   │           └── interfaces
│   │   │               └── otherimpl
│   │   │                   └── CircleImpl.class
│   │   └── module-info.class
│   └── app.main
│       ├── com
│       │   └── sample
│       │       └── app
│       │           └── App.class
│       └── module-info.class
└── src
    ├── app.interfaces
    │   ├── com
    │   │   └── sample
    │   │       └── app
    │   │           └── interfaces
    │   │               └── Circle.java
    │   └── module-info.java
    ├── app.interfaces.impl
    │   ├── com
    │   │   └── sample
    │   │       └── app
    │   │           └── interfaces
    │   │               └── impl
    │   │                   └── CircleImpl.java
    │   └── module-info.java
    ├── app.interfaces.otherimpl
    │   ├── com
    │   │   └── sample
    │   │       └── app
    │   │           └── interfaces
    │   │               └── otherimpl
    │   │                   └── CircleImpl.java
    │   └── module-info.java
    └── app.main
        ├── com
        │   └── sample
        │       └── app
        │           └── App.java
        └── module-info.java

44 directories, 16 files

Step 2: Generate jar files by executing below commands.


Create jars directory.
$mkdir jars
$
$ls
jars    out src

Generate jar files from modules by executing below commands.

jar --create --file jars/app.interfaces.jar -C out/app.interfaces .

jar --create --file jars/app.interfaces.impl.jar -C out/app.interfaces.impl .

jar --create --file jars/app.interfaces.otherimpl.jar -C out/app.interfaces.otherimpl .

jar --create --file jars/app.main.jar  --main-class=com.sample.app.App -C out/app.main .


Total project structure looks like below.
.
├── jars
│   ├── app.interfaces.impl.jar
│   ├── app.interfaces.jar
│   ├── app.interfaces.otherimpl.jar
│   └── app.main.jar
├── out
│   ├── app.interfaces
│   │   ├── com
│   │   │   └── sample
│   │   │       └── app
│   │   │           └── interfaces
│   │   │               └── Circle.class
│   │   └── module-info.class
│   ├── app.interfaces.impl
│   │   ├── com
│   │   │   └── sample
│   │   │       └── app
│   │   │           └── interfaces
│   │   │               └── impl
│   │   │                   └── CircleImpl.class
│   │   └── module-info.class
│   ├── app.interfaces.otherimpl
│   │   ├── com
│   │   │   └── sample
│   │   │       └── app
│   │   │           └── interfaces
│   │   │               └── otherimpl
│   │   │                   └── CircleImpl.class
│   │   └── module-info.class
│   └── app.main
│       ├── com
│       │   └── sample
│       │       └── app
│       │           └── App.class
│       └── module-info.class
└── src
    ├── app.interfaces
    │   ├── com
    │   │   └── sample
    │   │       └── app
    │   │           └── interfaces
    │   │               └── Circle.java
    │   └── module-info.java
    ├── app.interfaces.impl
    │   ├── com
    │   │   └── sample
    │   │       └── app
    │   │           └── interfaces
    │   │               └── impl
    │   │                   └── CircleImpl.java
    │   └── module-info.java
    ├── app.interfaces.otherimpl
    │   ├── com
    │   │   └── sample
    │   │       └── app
    │   │           └── interfaces
    │   │               └── otherimpl
    │   │                   └── CircleImpl.java
    │   └── module-info.java
    └── app.main
        ├── com
        │   └── sample
        │       └── app
        │           └── App.java
        └── module-info.java

45 directories, 20 files


Step 3: Execute below command to run the application from jar files
$java --module-path jars/:$JAVA_HOME/jmods -m app.main/com.sample.app.App
Going to get instances
Area : 314.285714285
Perimeter : 62.857142857
Area : 314.0
Perimeter : 62.800000000000004

Step 4: Generate image from the jar files by executing below command.

jlink --module-path jars/:$JAVA_HOME/jmods --add-modules app.main,app.interfaces.impl,app.interfaces.otherimpl --output image


Above command creates ‘image’ folder. Open image folder, you can see folders like bin, conf etc.,

$./image/bin/java --list-modules
app.interfaces
app.interfaces.impl
app.interfaces.otherimpl
app.main
java.base@12.0.1

Execute below command to run App.java application.

./image/bin/java -m app.main/com.sample.app.App

$./image/bin/java -m app.main/com.sample.app.App
Going to get instances
Area : 314.0
Perimeter : 62.800000000000004
Area : 314.285714285
Perimeter : 62.857142857



Previous                                                 Next                                                 Home

No comments:

Post a Comment