Compiler OpenJDK 8 pour l’embarqué

Thomas Lorblanchès

16/10/2015

big coffee
little coffee

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

$ sudo apt-get install mercurial (1)
$ hg clone http://hg.openjdk.java.net/jdk8u/jdk8u60 (2)
$ cd jdk8u60
$ bash ./get_source.sh (3)
$ sudo apt-get install openjdk8-jdk (4)
$ sudo apt-get build-dep openjdk-8 (5)
  1. OpenJDK utilise Mercurial pour ses dépôts de source

  2. Téléchargement du dépôt racine

  3. Téléchargement des sous-dépôts ("forêt")

  4. Java 7 ou 8 est requis pour compiler OpenJDK 8

  5. Installation des dépendances de compilation

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%.

Kernel

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

Zero

VM sans code assembleur, interpréteur seulement.

Zero-Shark

VM Zero avec compilateur JIT utilisant LLVM.

Tailles par défaut et performance des VM x86

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

Server 64bits

server

15.5Mo

70.9 ops/m

Server 32bits

server

13.5Mo

62.9 ops/m

Client 32bits

client

8.4Mo

43.9 ops/m

Minimal 32bits

minimal1

5.8Mo

40.4 ops/m

Zero 32 bits

zero

7.0Mo

1.4 ops/m

Shark 32 bits

zeroshark

19.8Mo

16.8 ops/m

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 : profiles compacts

Nouveauté Java 8.

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

Génération des profiles 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

  • 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%
  • 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

Inconvénient : temps de chargement des classes / démarrage de l’application

On en est où ?

VM Minimal avec profile 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)

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.

Des questions ?

duke