La modularisation avant l’heure : Compiler OpenJDK 8 en 10Mo

Thomas Lorblanchès

22/04/2016

big coffee
little coffee

OpenJDK ?

thinking

Minimisation : Pourquoi faire ?

snowball

Embarqué

FlamingGodzilla

Sécurité

java cloud

Cloud / VM / Conteneur / [insert your buzzword here]

Pré-requis (Debian et dérivées)

  • Récupération des sources :

$ sudo apt-get install mercurial
$ hg clone http://hg.openjdk.java.net/jdk8u/jdk8u60
$ cd jdk8u60
$ bash ./get_source.sh
  • Installation des dépendances de compilation :

$ sudo apt-get install openjdk8-jdk
$ sudo apt-get build-dep openjdk-8

Organisation des sources (dépôt racine)

jdk src root

Organisation des sources ("forêt")

jdk src full

Compilation d’OpenJDK 8

  • Configuration de la compilation :

$ bash ./configure --with-jvm-variants=server \
                   --with-debug-level=release \
                   --disable-debug-symbols --disable-zip-debug-info \
                   --enable-unlimited-crypto
  • Aide sur les options de configuration :

$ bash ./configure --help
  • Compilation :

$ make all

Etat des lieux initial : 98.3Mo

jdk8 server

Types de VM

  • Server : VM par défaut, meilleures perfos, plus grosse.

  • Client : VM 32bits optimisée pour les applications clientes (temps de démarrage).

  • Minimal : JEP-148, VM 32bits, empreinte minimale, dégradation perfo < 5%.

  • Zero : VM sans code assembleur, interpréteur seulement.

  • Zero-Shark : VM Zero avec compilateur JIT utilisant LLVM.

  • Kernel : Ancêtre de Minimal (Java 6), Windows seulement, non maintenue.

  • Core : Interpréteur seulement. Utilisé pour le "bootstrap" de la compilation pour le portage sur PowerPC/AIX.

Tailles et perfo des VM x86

VMOption de configuration
--with-jvm-variants=
Taille libjvm.soScore SPECjvm2008

Server 64b

server

15.5Mo

70.9 ops/m

Server 32b

server

13.5Mo

62.9 ops/m

Client 32b

client

8.4Mo

43.9 ops/m

Minimal 32b

minimal1

5.8Mo

40.4 ops/m

Zero 32b

zero

7.0Mo

1.4 ops/m

Shark 32b

zeroshark

19.8Mo

16.8 ops/m

Aparté : Projet "Mobile"

DukePhoning
The goal of this Project is to focus on porting the JDK to popular mobile platforms such as iOS, Android, and Windows.
— http://openjdk.java.net/projects/mobile/
  • JDK 9 based port

  • Support at minimum the equivalent of JDK 8 compact2 profile

  • iOS x64 and arm64 (arm64 will be provided via Zero interpreter)

  • Android x86 and arm (arm will be provided via Zero interpreter)

Tailles des VM

Make necessary modifications so that we can optionally build a small VM no larger than 3MB. (For reference, the client and server VMs are currently around 6 and 9MB, respectively.)
— JEP-148
question

Optimisations de libjvm.so

  • Edition des liens dynamique avec la lib C++ de l’OS :

    • --with-stdc++lib=dynamic

    • Gain : -102ko

  • Compilation optimisée pour la taille :

    • --with-extra-cflags=-Os

    • Gain : -1.8Mo sur libjvm.so (VM Minimal)

  • Stripping des binaires :

    • find . -exec strip --strip-unneeded {} \;

    • Gain : -1Mo sur libjvm.so (VM Minimal)

Résumé de l’optimisation de la taille de libjvm.so

VMTaille libjvm.so par défautTaille "optimisée"

Server 64bits

15.5Mo

8.8Mo

Server 32bits

13.5Mo

7.1Mo

Client 32bits

8.4Mo

4.1Mo

Minimal 32bits

5.8Mo

2.8Mo

Zero 32 bits

7.0Mo

3.4Mo

Shark 32 bits

19.8Mo

14.5Mo

Point sécurité

debian

Utilisation des options de durcissement Debian
(cf. https://wiki.debian.org/Hardening).

--with-extra-cflags='-Os -D_FORTIFY_SOURCE=2
-fstack-protector-strong'

--with-extra-ldflags='-Xlinker -z -Xlinker relro'

Prix de la sécurité : +139ko (VM Minimal) sans impact perfo mesurable

duke wall

Et les ARM ?

Optimisation de rt.jar

cesar

Profils compacts

Compact profiles are sort of a poor man’s module system.
— Mark Reinhold
compact profiles

Génération des profils compacts

$ make profiles
Type de JRETaille rt.jar

JRE complet

61.7Mo

Compact 3

30.5Mo

Compact 2

24.8Mo

Compact 1

13.9Mo

Compression de rt.jar

Archive

Par défaut, rt.jar n’est pas compressé !

$ zipinfo images/j2re-compact1-image/lib/rt.jar
[...]
4689 files, 13858994 bytes uncompressed, 13858994 bytes compressed: 0.0%

Compression de rt.jar

Archive

Compiler avec COMPRESS_JARS=true :

$ make all COMPRESS_JARS=true
$ make profiles COMPRESS_JARS=true
$ zipinfo images/j2re-compact1-image/lib/rt.jar
[...]
4689 files, 13858994 bytes uncompressed, 6574887 bytes compressed: 52.6%

Tailles rt.jar compressés

Type de JRESans compressionAvec compression

JRE complet

61.7Mo

30.1Mo

Compact 3

30.5Mo

14.9Mo

Compact 2

24.8Mo

12.0Mo

Compact 1

13.9Mo

7.1Mo

On en est où ?

VM Minimal avec profil compact 1 et compression.

jre8 compact1 jarcompress

On peut gratter encore un peu ?

  • lib/ext (1.6Mo) : packages optionnels

    • localedata.jar (1.1Mo) : données de localisation pour java.text et java.util (43 langues !)

    • sunec.jar (35ko) + lib/{arch}/libsunec.so (180ko) : crypto courbes elliptiques

    • sunjce_provider.jar (253ko) + lib/jce.jar (91ko) : Impl+API crypto (a)symétrique

    • sunpkcs11.jar (230ko) + lib/{arch}/libj2pkcs11.so (63ko) : PKCS#11 (crypto tokens)

  • lib/jsse.jar (303ko) : Java Secure Socket Extension (TLS/SSL)

Impact sur le code "utilisateur"

  • Analyse des dépendances avec jdeps

$ jdeps -v -profile hello-1.0-SNAPSHOT.jar
hello-1.0-SNAPSHOT.jar -> /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar (compact1)
   Main         -> java.lang.Object                 compact1
   Main         -> java.lang.String                 compact1
  • Limiter les dépendances externes

    • Utiliser java.util.logging au lieu de logback / log4j

    • Utiliser javax.xml au lieu d’un parser externe

    • Supprimer les dépendances transitives optionnelles / non utilisées

  • Utiliser jdeps sur les dépendances externes

Et Java 9 ?

55 modules !

modules
Figure 1. Modules Java 9 (source : Mark Reinhold, JFokus 2015)

Nouveaux outils

  • jdeps (depuis Java 8) : analyse des dépendances

$ jdeps -profile helloworld.jar
helloworld.jar -> java.base (compact1)
   test (helloworld.jar)
      -> java.io                                            compact1
      -> java.lang                                          compact1
  • jlink (Java 9) : création d’images JVM sur mesure (cf. JEP-282)

  • Nouveau format JMOD

Des questions ?

duke