Android Platform Implementation Details

The JDK 9 Android port supports both x86 and arm execution on Android emulators or devices. The x86 implementation uses the standard Hotspot JIT but the ARM 32-bit implementation is restricted to the Zero interpreter.

Build Requirements

Build machine

The Android JDK 9 build requires a 64-bit Linux System capable of running the Android NDK and SDK binaries.

Android NDK & SDK

Our JDK 9 Mobile project requires the Android NDK and SDK which can be downloaded from Android developer site. When downloading the SDK, select the Linux package from the "SDK Tools Only" section. The sources can currently be built using NDK version r10e and compiling for API level 19.

https://developer.android.com/sdk/index.html

Follow the instructions here for installing the Linux 64-bit (x86) Android NDK.

https://developer.android.com/ndk/guides/setup.html

Generating standalone toolchains for the builds

The dependent libraries and JDK build require a traditional standalone gnu toolchain to be available rather than the default layout of the Android NDK distribution. In addition, the JDK requires the toolchain to be in the form of a devkit. This amounts to having a devkit.info at the top directory of each required toolchain. Follow these instructions for this setup.


$HOME/jdk9mobile/android-ndk-r10b/build/tools/make-standalone-toolchain.sh \
--arch=arm \
--platform=android-19 \
--install-dir=$HOME/jdk9mobile/android-ndk-r10b/generated-toolchains/android-arm-toolchain

Put the following three lines in a file named devkit.info in the generated toolkit

DEVKIT_NAME="Android ARM"
DEVKIT_TOOLCHAIN_PATH="$DEVKIT_ROOT/arm-linux-androideabi/bin"
DEVKIT_SYSROOT="$DEVKIT_ROOT/sysroot" i

$HOME/jdk9mobile/android-ndk-r10b/build/tools/make-standalone-toolchain.sh/build/tools/make-standalone-toolchain.sh \
--arch=x86 \
--platform=android-19 \
--install-dir=$HOME/jdk9mobile/android-ndk-r10b/generated-toolchains/android-x86-toolchain

Put the following three lines in a file named devkit.info in the generated toolkit

DEVKIT_NAME="Android X86"
DEVKIT_TOOLCHAIN_PATH="$DEVKIT_ROOT/i686-linux-android/bin"
DEVKIT_SYSROOT="$DEVKIT_ROOT/sysroot"

For more information, please refer to this URL:

http://developer.android.com/ndk/guides/standalone_toolchain.html

libffi (required for ARM builds only)

The Zero interpreter used in our Android arm port requires a third party library for calling native functions. This library is libffi (Foreign Function Interface Library). We are currently working with version 3.2.1 of this library.

The libffi 3.2.1 sources can be downloaded from here:

https://sourceware.org/libffi/

Download the bundle and untar it to a working directory, "cd" into that directory and then execute the following commands:

# !/bin/csh
#
# I coulnd't get the --prefix=`pwd`/build_android-arm to cause the include
# and lib to show up in ./build_android-arm.  The build copied the lib
# but not the includes.  The current prefix is the default location for
# generated binaries which already included the header files so I 
# just linked the directory name I wanted.  
#
# Customize the following paths to match your setup
#
setenv ANDROID_DEVKIT $HOME/jdk9mobile/android-ndk-r10b/generated-toolchains/android-arm-toolchain
setenv PATH $ANDROID_DEVKIT/bin:$PATH
#
bash configure --host=arm-linux-androideabi --prefix=`pwd`/arm-unknown-linux-androideabi
make clean
make
make install
rm build_android-arm
ln -s arm-unknown-linux-androideabi build_android-arm

The "make install" will build the library and populate the include and lib directories in build_android-arm with the built libffi library artifacts needed to build the JDK.

libfreetype

The FreeType 2.6.2 sources can be downloaded from here:

http://freetype.org/download.html

To build an Android x86 distribution, download the sources, cd to the top directory and run these commands:

# !/bin/csh
#
# Customize the following paths to match your setup
#
setenv ANDROID_DEVKIT $HOME/jdk9mobile/android-ndk-r10b/generated-toolchains/android-x86-toolchain 
setenv PATH $ANDROID_DEVKIT/bin:$PATH
#
./configure --host=i686-linux-android \
--prefix=`pwd`/build_android-i686 \
--without-zlib \
--with-png=no \
--with-harfbuzz=no
make clean
make
make install

The output of the build will be stored in the build_android-i686 directory

To build an Android arm distribution, run these commands:

# !/bin/csh
#
# Customize the following paths to match your setup
#
setenv ANDROID_DEVKIT $HOME/jdk9mobile/android-ndk-r10b/generated-toolchains/android-arm-toolchain 
setenv PATH $ANDROID_DEVKIT/bin:$PATH
#
bash configure \
--host=arm-linux-androideabi \
--prefix=`pwd`/build_android-arm \
--without-zlib \
--with-png=no \
--with-harfbuzz=no
make clean
make
make install

The output of the build will be stored in the build_android-arm directory

Building the JDK

Once you have the required tools and libraries built, download the mobile/dev sources, customize the build commands below to match your build system setup and run the build script.

Downloading the sources

hg clone http://hg.openjdk.java.net/mobile/dev mobile-dev
cd mobile-dev
sh get_source.sh

Build command for x86

# !/bin/csh
#
# Customize the following paths to match your setup
#
setenv FREETYPE_DIR $HOME/jdk9mobile/freetype-2.6.2/build_android-i686
setenv CUPS_DIR $HOME/jdk9mobile/cups/include
setenv ANDROID_DEVKIT $HOME/jdk9mobile/android-ndk-r10b/generated-toolchains/android-x86-toolchain 
#
cd mobile-dev
bash configure \
--enable-option-checking=fatal \
--build=x86_64-unknown-linux-gnu \
--host=i686-linux-android \
--target=i686-linux-android \
--disable-warnings-as-errors \
--enable-headless-only \
--with-jdk-variant=normal \
--with-jvm-variants=client \
--with-cups-include=$CUPS_DIR \
--with-devkit=$ANDROID_DEVKIT \
--with-debug-level=release \
--with-freetype-lib=$FREETYPE_DIR/lib \
--with-freetype-include=$FREETYPE_DIR/include/freetype2

cd build/android-x86-normal-client-release
make images

Build command for arm

# !/bin/csh
#
# Customize the following paths to match your setup
#
setenv FREETYPE_DIR   $HOME/jdk9mobile/freetype-2.6.2/build_android-arm
setenv CUPS_DIR       $HOME/jdk9mobile/cups/include
setenv ANDROID_DEVKIT $HOME/jdk9mobile/android-ndk-r10b/generated-toolchains/android-arm-toolchain
setenv LIBFFI_DIR     $HOME/jdk9mobile/libffi-3.2.1/build_android-arm

cd mobile-dev
bash configure \
--enable-option-checking=fatal \
--build=x86_64-unknown-linux-gnu \
--host=arm-linux-androideabi \
--target=arm-linux-androideabi \
--disable-warnings-as-errors \
--enable-headless-only \
--with-jdk-variant=normal \
--with-jvm-variants=zero \
--with-libffi-include=$LIBFFI_DIR/include \
--with-libffi-lib=$LIBFFI_DIR/lib \
--with-cups-include=$CUPS_DIR \
--with-devkit=$ANDROID_DEVKIT \
--with-debug-level=release \
--with-freetype-lib=$FREETYPE_DIR/lib \
--with-freetype-include=$FREETYPE_DIR/include/freetype2

cd build/android-arm-normal-zero-release
make images

Running your built Java 9 binaries on Android

Make sure you have the Android SDK tools and platform-tools directory on your path.


# Create a 32-bit ARM AVD and then startup the Android emulator.  Skip
this step if you intend on running Java on Android ARM devices.

emulator64-arm -avd {your_arm_avd}

# Push the Java JRE binaries to the emulator

cd mobile-dev/build/android-arm-normal-zero-release/images
adb push jre /data/app/jre

# run a shell on the emulated device

adb shell

# Setup an environment variable required to run Java
setenv LD_LIBRARY_PATH /data/app/jre/lib/arm/jli:/data/app/jre/lib:/data/app/jre/lib/arm/server:$LD_LIBRARY_PATH
cd /data/app/jre/bin

# Run Java
./java -Djava.home=/data/app/jre -version
OpenJDK Runtime Environment (build 9-internal+0-2016-01-26-135852.bvandett.mobile-dev)
OpenJDK Zero VM (build 9-internal+0-2016-01-26-135852.bvandett.mobile-dev, interpreted mode)

Known Issues

1. If you get a message that the binary can't be run due to PIE issues, the JDK build needs to have some additional CFLAGS (-fPIE -pie) added to produce compatible binaries. This issue appears to only impact the "java" executable and does not impact shared libraries. Also, this issue only impacts newer Android running API level 21 or newer.