Building AOSP 7.x Nougat with only 8 GiB RAM

This is a problem that I ran across recently. Building the whole AOSP code base is a big task, and normally you would choose a machine with plenty of RAM. But, sometimes you need to build on a lesser machine. It happened to me when I was on the road and I wanted to run a build on my laptop, which has 8 GiB RAM, and a dual core hyper-threaded Intel i7 CPU. I have used this set up with Marshmallow and earlier versions without problem – it just takes a while, that’s all.

Contents


The problem

The problem manifests itself as a failed build after 90 minutes or so with a message similar to this:

[ 45% 16221/35670] Building with Jack:...k_intermediates/with-local/classes.dex
FAILED: /bin/bash out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/with-local/classes.dex.rsp
Out of memory error (version 1.2-rc4 'Carnac' (298900 f95d7bdecfceb327f9d201a1348397ed8a843843 by android-jack-team@google.com)).
GC overhead limit exceeded.
Try increasing heap size with java option '-Xmx'.
Warning: This may have produced partial or corrupted output.
[ 45% 16221/35670] Building with Jack:...colorpicker_intermediates/classes.jack
ninja: build stopped: subcommand failed.
build/core/ninja.mk:148: recipe for target 'ninja_wrapper' failed
make: *** [ninja_wrapper] Error 1

#### make failed to build some targets (01:26:54 (hh:mm:ss)) ####

The root of the problem is that jack-server (not Jack itself) has run out of heap. So, what is jack-server?


Some background information on Jack and jack-server

Jack is an Android toolchain that compiles Java source into Android dex bytecode. It replaces the previous Android toolchain, which consists of multiple tools, such as javac, ProGuard, jarjar, and dx. Jack is used from Marshmallow onwards.

In Nougat, jack-server was introduced to handle a pool of Jack compiler instances in order to limit memory usage and benefit from already warm instances. Jack-server is written in Java and is run in a Java VM. It is installed into ~/.jack-server when you run the first AOSP build.


The Java heap

AOSP 7 requires OpenJDK 8 to build. I took these measurements using OpenJDK 8, version 1.8.0_131 on Ubuntu 16.04.2:

$ java -version
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-8u131-b11-2ubuntu1.16.04.3-b11)
OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode)

Now, let’s look at the default heap size on two different machines. The default heap size scales according to the total amount of memory fitted, ignoring the swap space. On a 16 GiB machine, it is over 3 GiB:

$ java -XshowSettings 2>&1  | grep Heap
    Max. Heap Size (Estimated): 3.47G

But, on an 8 GiB machine, it is less than 2 GiB:

$ java -XshowSettings 2>&1  | grep Heap
    Max. Heap Size (Estimated): 1.71G

It turns out that jack-server needs about 3 GiB to build a typical AOSP Nougat target, and so it fails if the machine doesn’t have enough RAM. Increasing the swap space makes no difference.
Jack-server is launched by a shell script named jack-admin which is in the prebuilts/sdk/tools directory. Digging around a little in there, I found the default arguments for the server (line 29)

JACK_SERVER_VM_ARGUMENTS="${JACK_SERVER_VM_ARGUMENTS:=-Dfile.encoding=UTF-8 -XX:+TieredCompilation}"

Lower down, I found the point that it launches jack-server (line 454)

JACK_SERVER_COMMAND="java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -cp $LAUNCHER_JAR $LAUNCHER_NAME"
      echo "Launching Jack server" $JACK_SERVER_COMMAND

That is all I needed to know. Now we can move on to the solution.


The solution

Once I understood the problem, it was just a question of changing the default heap size when jack-server is launched. To fix it, you need to edit
~/.jack-settings, and add this line

JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096m"

Then, restart jack-server – otherwise if it is running in the background it will continue to use the old Xmx value:

$ prebuilts/sdk/tools/jack-admin kill-server
$ prebuilts/sdk/tools/jack-admin start-server
Launching Jack server java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=/tmp -Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096m
-cp /home/chris/.jack-server/launcher.jar com.android.jack.launcher.ServerLauncher

Then you can build AOSP 7.x on an 8 GiB machine. The build is not fast – a little less than 3 hours for me - but at least it completes.

For more information about Android and AOSP, you may want to consider one of my in-depth training courses:
Android Porting and Android Internals.

Chris Simmonds, Author, trainer, consultant.