[JAVA] Problems and workarounds that create an unusually large runtime with jlink in openjdk

I wasn't satisfied with Jib and I was caught when I tried to play with jlink in search of a lightweight container. As soon as I looked it up, I found that libjvm.so was overwhelmingly bloated. But why?

If you try google with openjdk jlink size, you will see various things.

https://matsumana.info/blog/2018/10/13/openjdk11-docker/ https://qiita.com/h-r-k-matsumoto/items/294eeb838cfd062d75b6

Mostly, it seems that the following issue's debian-based openjdk package jlink has reached the case where debug symbols are included.

https://github.com/docker-library/openjdk/issues/217

This time it happened on RHEL system (CentOS 7), but I think the same thing is happening. Looking at the cases where the same openjdk can be avoided with the alpine version, it seems that openjdk is not bad.

I don't know the detailed cause like that, but I will write the procedure and workaround to reproduce it. (The behavior may change with a package update.)

Reproduction procedure (as of 2/21)

Environment to be executed this time

$ cat /etc/redhat-release
Fedora release 28 (Twenty Eight)

I haven't written it this time, but I have confirmed it with openjdk 11 in the yum repository of CentOS 7.

Install from yum repository and try

$ sudo dnf install java-9-openjdk-jmods.x86_64 java-11-openjdk-jmods.x86_64

$ export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.2.7-0.fc28.x86_64
$ JAVA_HOME/bin/jlink --compress 2 --module-path "$JAVA_HOME/jmods" --add-modules java.base --output "jre-$(basename $JAVA_HOME)"

$ export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.2.7-0.fc28.x86_64
$ JAVA_HOME/bin/jlink --compress 2 --module-path "$JAVA_HOME/jmods" --add-modules java.base --output "jre-$(basename $JAVA_HOME)"

$ du -hs jre-java-*
613M    jre-java-11-openjdk-11.0.2.7-0.fc28.x86_64
407M    jre-java-9-openjdk-9.0.4.11-6.fc28.x86_64

$ ls -l jre-*/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 624872128 February 21 03:48 jre-java-11-openjdk-11.0.2.7-0.fc28.x86_64/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 410593824 February 21 03:47 jre-java-9-openjdk-9.0.4.11-6.fc28.x86_64/lib/server/libjvm.so

Workaround: Use OpenJDK binaries distributed at jdk.java.net

I tried everything from 9 to 12 for some reason.

$ curl -LO https://download.java.net/java/GA/jdk11/9/GPL/openjdk-11.0.2_linux-x64_bin.tar.gz
$ curl -LO https://download.java.net/java/GA/jdk12/32/GPL/openjdk-12_linux-x64_bin.tar.gz
$ curl -LO https://download.java.net/java/GA/jdk9/9.0.4/binaries/openjdk-9.0.4_linux-x64_bin.tar.gz
$ curl -LO https://download.java.net/java/GA/jdk10/10.0.2/19aef61b38124481863b1413dce1855f/13/openjdk-10.0.2_linux-x64_bin.tar.gz

$ tar xzf openjdk-9.0.4_linux-x64_bin.tar.gz
$ tar xzf openjdk-10.0.2_linux-x64_bin.tar.gz
$ tar xzf openjdk-11.0.2_linux-x64_bin.tar.gz
$ tar xzf openjdk-12_linux-x64_bin.tar.gz

$ for dirpath in jdk-9.0.4 jdk-10.0.2 jdk-11.0.2 jdk-12; do
>   export JAVA_HOME=$PWD/$dirpath
>   $JAVA_HOME/bin/jlink --compress 2 --module-path "$JAVA_HOME/jmods" --add-modules java.base --output "jre-$(basename $JAVA_HOME)"
> done

$ du -hs jre-jdk-*
33M     jre-jdk-10.0.2
35M     jre-jdk-11.0.2
36M     jre-jdk-12
32M     jre-jdk-9.0.4

$ ls -l jre-*/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 624872128 February 21 03:48 jre-java-11-openjdk-11.0.2.7-0.fc28.x86_64/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 410593824 February 21 03:47 jre-java-9-openjdk-9.0.4.11-6.fc28.x86_64/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 21405080 February 21 04:12 jre-jdk-10.0.2/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 22812128 February 21 04:12 jre-jdk-11.0.2/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 23027240 February 21 04:12 jre-jdk-12/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 20352536 February 21 04:12 jre-jdk-9.0.4/lib/server/libjvm.so

It doesn't seem to happen. The size is different by one digit. I was looking for this.

(Unconfirmed operation) Workaround: strip -p --strip-unneeded

** I haven't confirmed if it works this way **

I tried to see this information. https://github.com/docker-library/openjdk/issues/217#issuecomment-430380403

Just use strip to strip symbols that don't affect execution.

$ strip -p --strip-unneeded jre-java-11-openjdk-11.0.2.7-0.fc28.x86_64/lib/server/libjvm.so
$ strip -p --strip-unneeded jre-java-9-openjdk-9.0.4.11-6.fc28.x86_64/lib/server/libjvm.so

$ ls -l jre-*/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 20025552 February 21 03:48 jre-java-11-openjdk-11.0.2.7-0.fc28.x86_64/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 16928088 February 21 03:47 jre-java-9-openjdk-9.0.4.11-6.fc28.x86_64/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 21405080 February 21 04:12 jre-jdk-10.0.2/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 22812128 February 21 04:12 jre-jdk-11.0.2/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 23027240 February 21 04:12 jre-jdk-12/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 20352536 February 21 04:12 jre-jdk-9.0.4/lib/server/libjvm.so

If you do it for the problem libjvm.so, you can see that the problem has been solved in terms of size. Rather small.

However, if you look at the nm command after doing this, you will not find any symbols at all, so it should be difficult to debug at a lower level than the JVM using gdb etc. (On the other hand, jdk.java.net remains, so gdb etc. should be usable)

Recommended Posts

Problems and workarounds that create an unusually large runtime with jlink in openjdk
Create an infinite scroll with Infinite Scroll and kaminari
Create an Annotator that uses kuromoji with NLP4J [007]
Create an EC site with Rails5 ④ ~ Header and footer ~
Maybe it works! Create an image with Docker and share it!
[rails] Problems that cannot be registered / logged in with devise
Introducing Lightsleep, an O / R mapping library that works only with Java Runtime and JDBC drivers