Help

Experiments with GraalVM native images (2/2)

The previous blog post was about the “normal way” of using GraalVM native images. In this blog post I use it to run Java code on Android without the usual limitations of “Android Java”. I.e. the Java code can be JDK 11 and include arbitrary libraries which is usually not possible when using Dalvik or ART. The obvious next step is to do the same with iOS, but this is for another blog post ;).

The first step is to create some Java code and include the maven plugin from Gluon “client-maven-plugin”. For GraphHopper I needed a snapshot version and so I included the gluonhq plugin repository, but this won’t be necessary once the next release is out.

You need lots of tooling for Android. First of all I got the latest GraalVM from Gluon:

wget https://download2.gluonhq.com/substrate/graalvm/graalvm-svm-linux-20.1.0-ea+26.zip

Unzip this and let GRAALVM_HOME point to it:

export GRAALVM_HOME=$BASE/graalvm-svm-linux-20.1-latest

Now you download the Android SDK and set an env variable to it:

export ANDROID_SDK=$BASE/android-sdk-linux

And you do the same for Android NDK:

export ANDROID_NDK=$BASE/android-sdk-linux/ndk/20.1.5948944/ 

The idea of “Gluon Mobile” is to use the same Java also for the mobile application code (“Java end-to-end”) without using the Android UI toolkit – instead these applications use JavaFX. For GrapHopper you can do the same but I wanted to provide a solution for developers with an existing “Android Java” application too and so I tried the client examples from Gluon to create a native library that can be used from an existing “Android Java” application. For that a very fresh GraalVM version was necessary which I built from sources:

# download a patched JDK from https://github.com/graalvm/labs-openjdk-11/releases/download/
export JAVA_HOME=/path/labsjdk-ce-11.0.6-jvmci-20.0-b02/
git clone https://github.com/graalvm/mx.git
export PATH=$PATH:$(pwd)/mx
git clone https://github.com/oracle/graal.git
cd graal/vm
mx clean
# without: polyglot stuff
mx -J-Xmx5g --env ce --disable-polyglot --disable-libpolyglot build

See this issue and this article or this script on how others did this.

But I couldn’t get it working. So I asked Gluon for some consulting and they improved their open source pipeline. After several days from them and also lots of further investment from myself we finally got it working! It is now possible to run the native GraphHopper library on my Android phone:

IDE Output when running GraphHopper native on Android

This means I created the native library libgraphhoppernative that I use from this Android NDK project a rather simple proof that it works looks like:

It works 🙂 !

We could even do the OpenStreetMap data import or use the public transit module as all libraries and language features should work without a problem unlike for “Android Java”. And the speed of one routing request is also good in my preliminary tests.

Unfortunately there are currently a few caveats:

  1. The memory usage is strange and the routing app crashes after being called a few times. Maybe we should not call it from the main thread but maybe there is a GraalVM bug. Will post this on their slack channel.
  2. The produced library file is over 55MB. I’m unsure why it is so large as the native library for linux is 15MB. Maybe this issue is related.
  3. The created native library currently only supports 64bit code. Work is in progress for 32 bit code by Oracle.
  4. The compilation takes several minutes and is very resource intense and sometimes crashes my laptop. Here again Oracle will improve the situation in the future according to my knowledge. But at the moment the development is horrible.
  5. Communication with the “Graal” code is currently ugly: from Java you call C code that calls the run_main method from Graal, which has no possibility to return something. So the communication happens via a file instead which we read from C again (we could do this in Java too).

So this technology is really cutting edge, but I’m still excited about it as it can enable Java to be really platform-independent again.

Until then you would probably better use our Android library. See also this discussion.

Happy Routing!