How to install and use Java 11 and JavaFX 11 on Raspberry Pi boards with ARMv6 processor

In a previous post “Installing Java and JavaFX on the Raspberry Pi”, you can read how to install BellSoft LibericaJDK to be able to run JavaFX applications with a graphical user interface on a Raspberry Pi with ARMv7 or ARMv8 processor.

But this won’t work for some (older) versions of the Raspberry Pi as these use an ARMv6 processor which is not compatible with the default OpenJDK 11 which is part of Raspberry Pi OS.

This post will guide you through the steps to have a working Java JDK and JavaFX 11 on these Raspberry Pi board versions.

Prepare a Raspberry Pi

ARMv6 Raspberry Pi board

For this post, I’m using an old Raspberry Pi B+ 1.2. To be sure which ARM-version is used, check the output of “cat /proc/cpuinfo” in the terminal:

$ cat /proc/cpuinfo

processor	: 0
model name	: ARMv6-compatible processor rev 7 (v6l)
BogoMIPS	: 697.95
Features	: half thumb fastmult vfp edsp java tls 
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x0
CPU part	: 0xb76
CPU revision	: 7

Hardware	: BCM2835
Revision	: 0010
Serial		: 000000005f9ba615
Model		: Raspberry Pi Model B Plus Rev 1.2

For a clear overview of the different board- and ARM-version, check this table on Wikipedia. The boards with ARMv6 are:

Prepare SD card with Raspberry Pi OS (Full)

We start with a fresh new Raspberry Pi OS on the SD card using the “Imager” tool.

When we now boot the Rasberry Pi board with an ARMv6 processor and check the Java version we get this result:

$ java -version
Error occurred during initialization of VM
Server VM is only supported on ARMv7+ VFP

As expected, the default included OpenJDK for ARM is build for version 7 or higher, so doesn’t work on this ARMv6-based Raspberry Pi B+ 1.2.

Change the Java JDK

The sources of Java are available through the open-source project OpenJDK. So anyone can build Java JDK packages - yes you can even do it yourself! - and luckily a lot of free pre-build versions are available.

Install Java 11 for ARMv6 provided by Azul

Only Azul seems to provide an ARMv6 version with there Zulu JDK, which is available for free!

Let’s get it from their download page and extract it on our Raspberry Pi.

$ cd /usr/lib/jvm
$ sudo wget https://cdn.azul.com/zulu-embedded/bin/zulu11.41.75-ca-jdk11.0.8-linux_aarch32hf.tar.gz
$ sudo tar -xzvf zulu11.41.75-ca-jdk11.0.8-linux_aarch32hf.tar.gz
$ sudo rm zulu11.41.75-ca-jdk11.0.8-linux_aarch32hf.tar.gz
$ ls -l
total 12
lrwxrwxrwx  1 root root   21 Jul 23 15:58 java-1.11.0-openjdk-armhf -> java-11-openjdk-armhf
drwxr-xr-x  9 root root 4096 Aug 20 11:41 java-11-openjdk-armhf
drwxr-xr-x  2 root root 4096 Aug 20 11:41 openjdk-11
drwxrwxr-x 10  111  122 4096 Jul 10 16:50 zulu11.41.75-ca-jdk11.0.8-linux_aarch32hf

OK, there it is! A new JDK on our board. Now let’s configure the OS to be aware of this new one.

$ sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/zulu11.41.75-ca-jdk11.0.8-linux_aarch32hf/bin/java 1
$ sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/zulu11.41.75-ca-jdk11.0.8-linux_aarch32hf/bin/javac 1

Now we can select the new JDK so it’s linked to the “java” and “javac” command.

$ sudo update-alternatives --config java
There are 2 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                                             Priority   Status
------------------------------------------------------------
* 0            /usr/lib/jvm/java-11-openjdk-armhf/bin/java                       1111      auto mode
  1            /usr/lib/jvm/java-11-openjdk-armhf/bin/java                       1111      manual mode
  2            /usr/lib/jvm/zulu11.41.75-ca-jdk11.0.8-linux_aarch32hf/bin/java   1         manual mode

Press <enter> to keep the current choice[*], or type selection number: 2
update-alternatives: using /usr/lib/jvm/zulu11.41.75-ca-jdk11.0.8-linux_aarch32hf/bin/java to provide /usr/bin/java (java) in manual mode

$ sudo update-alternatives --config javac
There are 2 choices for the alternative javac (providing /usr/bin/javac).

  Selection    Path                                                              Priority   Status
------------------------------------------------------------
* 0            /usr/lib/jvm/java-11-openjdk-armhf/bin/javac                       1111      auto mode
  1            /usr/lib/jvm/java-11-openjdk-armhf/bin/javac                       1111      manual mode
  2            /usr/lib/jvm/zulu11.41.75-ca-jdk11.0.8-linux_aarch32hf/bin/javac   1         manual mode

Press <enter> to keep the current choice[*], or type selection number: 2
update-alternatives: using /usr/lib/jvm/zulu11.41.75-ca-jdk11.0.8-linux_aarch32hf/bin/javac to provide /usr/bin/javac (javac) in manual mode

If everything went well, we should be able to check the Java version now…

$ java -version
openjdk version "11.0.8" 2020-07-14 LTS
OpenJDK Runtime Environment Zulu11.41+75-CA (build 11.0.8+10-LTS)
OpenJDK Client VM Zulu11.41+75-CA (build 11.0.8+10-LTS, mixed mode)

We have a winner! We now successfully replaced the default OpenJDK 11 (which only works on ARMv7+) with the Azul Zulu JDK which works on ARMv6.

Testing with a non-compiled Java file

Let’s try out the newly installed Java JDK. Since Java 11, we can run Java-files directly without the need to compile them. Let’s create a simple file with nano and run it.

$ cd /home/pi
$ nano HelloWorld.java

public class HelloWorld {
    public static void main (String[] args) {
        System.out.println("Hello World");
    }
}

$ java HelloWorld.java
Hello World

Perfect! Java works as expected, but it takes about 15 seconds before the “Hello World” is shown on this old board dating from 2014.

Graphical user interfaces with JavaFX

If you also want to use JavaFX user interfaces, additional steps are needed as this library is not included in the JDK 11. It is developed as an independant open-source project on openjfx.io. The main contributor and maintainer is Gluon. They also offer commercial support to companies who want to use JavaFX for desktop and mobile application development.

Make sure you successfully updated to Azul Zulu JDK 11 before proceeding with the next steps.

Install JavaFX 11 for ARMv6 provided by GluonHQ

We are going to use the free public version provided by Gluon on their download page.

$ cd /home/pi
$ wget -O javafx.zip https://gluonhq.com/download/javafx-11-0-2-sdk-armv6hf/
$ unzip javafx.zip
$ rm javafx.zip

We can now check the JavaFX library which was unpacked in “armv6hf-sdk”:

pi@raspberrypi:~ $ ls -l
total 44
drwxr-xr-x 4 pi pi 4096 Mar 12  2019 armv6hf-sdk
drwxr-xr-x 2 pi pi 4096 Aug 20 11:40 Bookshelf
drwxr-xr-x 2 pi pi 4096 Aug 20 12:10 Desktop
...

$ ls -l armv6hf-sdk/
total 8
drwxr-xr-x 8 pi pi 4096 Mar 12  2019 legal
drwxr-xr-x 2 pi pi 4096 Mar 12  2019 lib

$ ls -l armv6hf-sdk/lib/
total 17124
-rw-r--r-- 1 pi pi  845637 Mar 12  2019 javafx.base.jar
-rw-r--r-- 1 pi pi 2761905 Mar 12  2019 javafx.controls.jar
-rw-r--r-- 1 pi pi  143926 Mar 12  2019 javafx.fxml.jar
-rw-r--r-- 1 pi pi 5270589 Mar 12  2019 javafx.graphics.jar
-rw-r--r-- 1 pi pi  294822 Mar 12  2019 javafx.media.jar
-rw-r--r-- 1 pi pi     992 Mar 12  2019 javafx.platform.properties
-rw-r--r-- 1 pi pi     113 Mar 12  2019 javafx.properties
-rw-r--r-- 1 pi pi   41802 Mar 12  2019 javafx-swt.jar
-rw-r--r-- 1 pi pi  786021 Mar 12  2019 javafx.web.jar
-rwxr-xr-x 1 pi pi   61200 Mar 12  2019 libdecora_sse.so
-rwxr-xr-x 1 pi pi   31428 Mar 12  2019 libglass_monocle.so
-rwxr-xr-x 1 pi pi   15946 Mar 12  2019 libglass_monocle_x11.so
-rwxr-xr-x 1 pi pi  200074 Mar 12  2019 libglass.so
-rwxr-xr-x 1 pi pi   22409 Mar 12  2019 libjavafx_font_freetype.so
-rwxr-xr-x 1 pi pi   20508 Mar 12  2019 libjavafx_font_pango.so
-rwxr-xr-x 1 pi pi   15206 Mar 12  2019 libjavafx_font.so
-rwxr-xr-x 1 pi pi  231402 Mar 12  2019 libjavafx_iio.so
-rwxr-xr-x 1 pi pi   43339 Mar 12  2019 libprism_common.so
-rwxr-xr-x 1 pi pi   54506 Mar 12  2019 libprism_es2_monocle.so
-rwxr-xr-x 1 pi pi   56505 Mar 12  2019 libprism_sw.so
-rw-r--r-- 1 pi pi 6598638 Mar 12  2019 src.zip

Test with a minimal JavaFX application

We are going to reuse the minimal JavaFX application which was created in this post “PiJava - Part 4 - Building a minimal JavaFX 11 application with Maven”. First, we need to clone the sources from GitHub:

$ cd /home/pi
$ git clone https://github.com/FDelporte/MinimalJavaFx11Application.git

To be able to build the application, we also need Maven to be installed.

$ sudo apt install maven

Now let’s build the application:

$ cd MinimalJavaFx11Application
$ mvn clean package

This will take some time as all the dependencies need to be downloaded.

When finished, we can now run the application with the following start command which points to the downloaded JavaFX library and the generated jar-application in the out-directory of “MinimalJavaFx11Application”:

$ sudo java --module-path /home/pi/armv6hf-sdk/lib
   --add-modules=javafx.controls
   -jar /home/pi/MinimalJavaFx11Application/out/MinimalJavaFx11Application-0.1-SNAPSHOT.jar

And there we have it! JavaFX running on an ARMv6 Raspberry Pi B+ 1.2!!!

Conclusion

Compared to the latest Raspberry Pi with a much faster processor and more memory, the application starts a lot slower on my 6-year old test board. But it works! Yes, really, it works :-)

Again this small-superhero-board proves to be able to handle everything, even the most modern Java versions on an old processor.


This article has also been published on “foojay.io - a place for friends of OpenJDK”