[JAVA] Problèmes et solutions de contournement qui créent un runtime anormalement volumineux avec jlink dans openjdk

Je n'étais pas satisfait de Jib et j'ai été surpris lorsque j'ai essayé de jouer avec jlink à la recherche d'un conteneur léger. Dès que je l'ai recherché, j'ai trouvé que libjvm.so était extrêmement gonflé. Mais pourquoi?

Si vous essayez google avec la taille openjdk jlink, vous verrez différentes choses.

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

Surtout, il semble que le package openjdk basé sur debian du problème suivant jlink ait atteint le cas où le symbole de débogage est inclus.

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

Cette fois, c'est arrivé dans le système RHEL (CentOS 7), mais je pense que la même chose se produit. En regardant les cas où le même openjdk peut être évité avec la version alpine, il semble que openjdk n'est pas mauvais.

Je ne connais pas la cause détaillée comme ça, mais j'écrirai la procédure et la solution de contournement pour la reproduire. (Le comportement peut changer avec une mise à jour du package.)

Procédure de reproduction (à partir du 21/02)

Environnement à exécuter cette fois

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

Je ne l'ai pas écrit cette fois, mais je l'ai confirmé dans openjdk 11 dans le référentiel yum de CentOS 7.

Installez à partir du référentiel yum et essayez

$ 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 21 février 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 21 février 03:47 jre-java-9-openjdk-9.0.4.11-6.fc28.x86_64/lib/server/libjvm.so

Solution: utilisez le binaire OpenJDK distribué sur jdk.java.net

J'ai tout essayé de 9 à 12 pour une raison quelconque.

$ 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 21 février 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 21 février 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 21 février 04:12 jre-jdk-10.0.2/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 22812128 21 février 04:12 jre-jdk-11.0.2/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 23027240 21 février 04:12 jre-jdk-12/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 20352536 21 février 04:12 jre-jdk-9.0.4/lib/server/libjvm.so

Cela ne semble pas arriver. La taille est différente d'un chiffre. Je cherchais ceci.

(Opération non confirmée) Solution de contournement: strip -p --strip-unneeded

** Je n'ai pas confirmé si cela fonctionne de cette façon **

J'ai essayé de voir ces informations. https://github.com/docker-library/openjdk/issues/217#issuecomment-430380403

Utilisez simplement une bande pour supprimer les symboles qui n'affectent pas l'exécution.

$ 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 21 février 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 21 février 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 21 février 04:12 jre-jdk-10.0.2/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 22812128 21 février 04:12 jre-jdk-11.0.2/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 23027240 21 février 04:12 jre-jdk-12/lib/server/libjvm.so
-rw-rw-r--.1 fukasawah fukasawah 20352536 21 février 04:12 jre-jdk-9.0.4/lib/server/libjvm.so

Si vous le faites pour le problème libjvm.so, vous pouvez voir que le problème a été résolu en termes de taille. Plutôt petit.

Cependant, si vous regardez la commande nm après avoir fait cela, le symbole ne sera pas du tout trouvé, il devrait donc être difficile de déboguer à un niveau inférieur à JVM en utilisant gdb etc. (D'un autre côté, jdk.java.net reste, donc gdb etc. devrait être utilisable)

Recommended Posts

Problèmes et solutions de contournement qui créent un runtime anormalement volumineux avec jlink dans openjdk
Créer un annotateur qui utilise kuromoji avec NLP4J [007]
Créer un site EC avec Rails5 ④ ~ En-tête et pied de page ~
Peut-être que ça marche! Créez une image avec Docker et partagez-la!
[rails] Problèmes qui ne peuvent pas être enregistrés / connectés avec l'appareil
Présentation de Lightsleep, une bibliothèque de mappage O / R qui fonctionne uniquement avec les pilotes Java Runtime et JDBC