Running Java on a PLCnext Control

To run Java on an PLCnext Control e.g. on the AXC F 2152, a Java Runtime Environment (JRE) must be available. There are two possible options. On the one hand you can install the whole JDK including the JRE for ARM 32 bit. This makes sense, if you intend to run more than one Java application or for testing purposes. On the other hand for a more dense all-in-one package it is recommended to use jlink. It combines modules and builds an all-in runtime image. It creates a bundle with just the necessary parts of the JDK needed for your application.

Installing OpenJDK

The binaries of OpenJDK for a lot of platforms can be found e.g. on AdoptOpenJDK. For the PLCnext Control AXC F 2152 the Linux arm32 jdk-12.0.2+10 is suitable. The installation is quite easy. Unpacking and optionally making the binaries known in the PATH.

Example for building an all-in runtime image

With Java 9, a new tool called jlink was introduced. It combines modules and builds an all-in runtime image. With jlink and modules it is possible to reduce the resources needed for your Java application. It creates a bundle with just the necessary parts of the JDK needed for your application.

Prerequisites

  • JDK for your host system
  • JDK for the controller

The binaries of OpenJDK for a lot of platforms can be found e.g. on AdoptOpenJDK. For this topic, we chose the Linux arm32 jdk-12.0.2+10 for the controller and its equivalent for a Windows x64 host system. We are using the following location of the JDKs:

C:
\---Java
    |
    +---jdk-12.0.2
    |       ...
    |
    \---jdk-12-ARM-32bit
            ...

Create an application module

In this example we are just printing a Hello World on the console. To use jlink we have to put this small application into a module. My starting point on the terminal is a folder called HelloWorld and a src folder with the following structure:

HelloWorld
\---src
    \---de.plcnext.hello
        |   module-info.java
        |
        \---de
            \---plcnext
                \---hello
                        HelloWorld.java

This is our small code example in the HelloWorld.java file:

package de.plcnext.hello;
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello PLCnext world!");
    }
}

And the module-info.java is needed to create the module:

module de.pxc.hello { }

After creating the source folder we compile our project. For this we use the following command on the terminal.

C:\Java\jdk-12.0.2\bin\javac.exe -d .\modules\de.plcnext.hello\ .\src\de.plcnext.hello\de\plcnext\hello\HelloWorld.java .\src\de.plcnext.hello\module-info.java

A modules folder and java classes are created:

HelloWorld
\---modules
    \---de.plcnext.hello
        |   module-info.class
        |
        \---de
            \---plcnext
                \---hello
                        HelloWorld.class

To test our module on the host system, we can run it with the following command:

C:\Java\jdk-12.0.2\bin\java.exe --module-path .\modules\ -m de.plcnext.hello/de.plcnext.hello.HelloWorld

This should output Hello PLCnext world!.

How to use jlink

Now we want to get this onto our device without the whole 300 MB JDK. For this we are using jlink without any additional parameters in the first step. But at first we need one more information, which additional modules are needed. This we will find out by analyzing our module with jdeps.

C:\Java\jdk-12.0.2\bin\jdeps.exe --module-path ".\modules\" --add-modules "de.plcnext.hello"

This tells us, we need java.base additionally to our module. As module-path we pick the path to our application and the path to the jmods of our target platform JDK. In this case C:\Java\jdk-12-ARM-32bit\jmods\.

Now our jlink call looks like this:

C:\Java\jdk-12.0.2\bin\jlink.exe --module-path ".\modules\;C:\Java\jdk-12-ARM-32bit\jmods\" --add-modules "de.plcnext.hello,java.base" --output HelloWorldjre

Note: Pay attention to the separators of the module-path and add-modules values these are dependent to the terminal you use.

The result is a HelloWorldjre folder with only about 45 MB. We copy this to our controller. In case of this example to
/opt/plcnext/projects/java/. We need to make the java file in the HelloWorldjre binary folder executable via chmod +x java and start our module

./java -m de.plcnext.hello/de.plcnext.hello.HelloWorld

It should run the application and output like before Hello PLCnext world!. By using some additional parameters of jlink you can strip down the package even more (in this example down to 28 MB) by using --strip-debug, --no-header-files, --no-man-pages and --compress=2. If you use this variant of compression, the package has the smallest size. However, this can lead to performance problems.