Slide 1

Slide 1 text

YAJUG - feb 2017 Rémi Forax Going Nuts Going Native Rémi Forax YAJUG - feb 2017

Slide 2

Slide 2 text

Me, Myself and I Maitre de conférence University Paris Est Marne la vallée Developer: OpenJDK, ASM, Tatoo, … Java Community Process Expert – Invokedynamic (JSR 292) – Lambda (JSR 335 + java.util/java.util.stream) – Jigsaw (JSR 376) – Amber (Java 10), Valhalla (Java 10 + 11)

Slide 3

Slide 3 text

Dramatic Intro !

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No reliable configuration ClassPath ? – Linear scan :( – If two versions of the same package exist ? => Jar Hell Example: CLASSPATH = …:asm-2.3.jar:…:asm-3.1.jar A newly introduced class of ASM 3.1 will use an old class of ASM 2.3 => compile time information is different from runtime info

Slide 6

Slide 6 text

No way to scale Down the platform Some libraries tend to be too big – OpenJDK 8 rt.jar => 66 Mb – Guava 20 => 2.3 Mb – Spring Context => 1.1 Mb on Maven Central IoT anyone ? and JDK classes are privileged :(

Slide 7

Slide 7 text

No Strong Encapsulation 2013 is a very bad year for Java security The JDK has only one line of defense :(

Slide 8

Slide 8 text

Going Nuts !

Slide 9

Slide 9 text

Jigsaw Let’s modularize Java in 6, 7, 8, 9 Aaargh stupid !!! – Adding security after the fact always fails ! – Java already works without it ! – Why not using OSGI bundle, JBoss module, Maven module … ?

Slide 10

Slide 10 text

The Jigsaw Sandwich Compile time Runtime

Slide 11

Slide 11 text

Module descriptor in mymodule/module-info.java module foo { requires java.base; requires bar; exports com.acme.my.package; } requires → module dependencies exports → packages visible by other modules (classpath == unamed module)

Slide 12

Slide 12 text

Example - ModuleTools A simple application – Allow to read/transform/write a module-info 4 packages – fr.umlv.moduletools.main ● command line – fr.umlv.moduletools.trasform ● chain transformations – fr.umlv.moduletools.api ● module input, module output – fr.umlv.moduletools.internal ● Uses ASM to read/write module-info.class ● Uses javac to read module-info.java

Slide 13

Slide 13 text

Packages dependencies – Java 8 java.* fr.umlv.moduletools.api fr.umlv.moduletools.internal fr.umlv.moduletools.main fr.umlv.moduletools.transform org.objectweb.asm.* asm5.jar

Slide 14

Slide 14 text

Modules - jigsaw java.base org.objectweb.asm.* asm5.jar module moduletools.main { requires java.base; requires moduletools.api: exports fr.umlv.moduletools.main; } fr.umlv.moduletools.main moduletools.main fr.umlv.moduletools.transform fr.umlv.moduletools.api moduletools.api fr.umlv.moduletools.internal java.compiler

Slide 15

Slide 15 text

Modules - jigsaw java.base org.objectweb.asm.* asm5.jar module moduletools.main { requires java.base; requires moduletools.api: exports fr.umlv.moduletools.main; } fr.umlv.moduletools.main moduletools.main fr.umlv.moduletools.transform fr.umlv.moduletools.api moduletools.api fr.umlv.moduletools.internal java.compiler

Slide 16

Slide 16 text

3 kind of requires 3 kinds of requires – default ● not transitive – transitive (1 hop) ● If B requires transitive C, if A requires B, A get all exports of C – static ● Requires at compile-time, maybe not present at runtime java --add-modules foo

Slide 17

Slide 17 text

Create module moduletools.main javac -d target/main/exploded/moduletools.main \ -sourcepath src/main/java/ \ $(find src/main/java/ -name "*.java") jar --create \ --file target/main/artifact/moduletools.main-1.0.jar \ --module-version=1.0 \ --main-class fr.umlv.moduletools.main.Main \ -C target/exploded/moduletools.main .

Slide 18

Slide 18 text

Layout of modules on disc Two layouts – Legacy layout, 1 module in 1 project, use --source-path – Multi-module layout, several modules in 1 project, use --module-source-path javac -d target/main/exploded \ --module-source-path src/main/java \ $(find src/main/java -name "*.java")

Slide 19

Slide 19 text

Multi-modules / module-source-path javac -d target/main/exploded \ --module-source-path src/main/java \ $(find src/main/java -name "*.java") On disc src/main/java ● moduletools.main module-info.java fr/umlv/moduletools/transform ● … .java fr/umlv/moduletools/main ● Main.java ● moduletools.api module-info.java ... a folder with a qualified name

Slide 20

Slide 20 text

Automatic module

Slide 21

Slide 21 text

Modules java.base org.objectweb.asm.* asm-6.jar module moduletools.main { requires moduletools.api: exports fr.umlv.moduletools.main; } fr.umlv.moduletools.main moduletools.main fr.umlv.moduletools.transform fr.umlv.moduletools.parser moduletools.api fr.umlv.moduletools.asm java.compiler module moduletools.api { requires java.compiler: requires asm; exports fr.umlv.moduletools.api; }

Slide 22

Slide 22 text

Create module moduletools.api javac -d target/main/exploded \ --module-source-path src/main/java \ -classpath deps/asm-6.jar \ $(find src/main/java -name "*.java") This doesn't compile !!

Slide 23

Slide 23 text

Mixing modules and jars Modules in module-path do not read (see) classes in classpath modulepath classpath (unamed module) java.compiler moduletools.main moduletools.api asm-6.jar OK ! NO ! java.base

Slide 24

Slide 24 text

Automatic modules (migration mode) Plain old jar in module-path – can be used in requires – can read modules – can read any jars from the classpath modulepath classpath (unamed module) another-jar.jar modulepath module moduletools.api { requires java.compiler: requires asm; exports …; } the jar may need to be renamed ! java.compiler moduletools.main moduletools.api asm-6.jar java.base

Slide 25

Slide 25 text

Create module moduletools.api javac -d target/main/exploded \ --module-source-path src/main/java \ --module-path deps \ $(find src/main/java -name "*.java") It works !

Slide 26

Slide 26 text

Run moduletools As legacy jars (Java 9 is compatible with Java <9) $ /usr/jdk/jdk-9/bin/java -classpath \ target/main/artifact/moduletools.api-1.0.jar: \ target/main/artifact/moduletools.main-1.0.jar: \ deps/asm-6.jar fr.umlv.moduletools.main.Main \ ... As modular jars $ java --module-path target/main/artifact:deps \ --module moduletools.main \ ...

Slide 27

Slide 27 text

Running on Java 9

Slide 28

Slide 28 text

Java 9 compatibility issues (1/2) The module system – disallow split packages classes of same package in 2 modules – disallow deep reflection by default changing final field, accessing private members, etc setAccessible can now fail !

Slide 29

Slide 29 text

Open Module / Open package Deep reflection must to be allowed explicitly with the directive opens module foo.bean { exports boo.bean.business; opens boo.bean.business; } Or you can open all the packages of a module open module foo.bean { exports boo.bean.business; }

Slide 30

Slide 30 text

Java 9 compatibility issues (2/2) The module system – disallow split packages – disallow deep reflection by default otherwise there is no security Some classes (sun.*, com.sun.*) of the JDK – have been deleted – are in an non exported packages (may be deleted in the future) otherwise you can not downsized the JDK

Slide 31

Slide 31 text

Demo !

Slide 32

Slide 32 text

Discovering usage of internal APIs $ jdeps --jdkinternals target deps/vertx-*.jar target -> JDK removed internal API target -> jdk.unsupported io.snowcamp.papaya.doc.Document -> sun.misc.BASE64Decoder (JDK removed internal) io.snowcamp.papaya.doc.Document -> sun.misc.BASE64Encoder (JDK removed internal) io.snowcamp.papaya.reflect.ReflectionSupport -> sun.misc.Unsafe internal (jdk.unsupported) vertx-internal-3.3.3.jar -> java.base vertx-internal-3.3.3.jar -> jdk.unsupported io.netty.handler.ssl.util.OpenJdkSelfSignedCertGenerator -> sun.security.util.ObjectIdentifier internal (java.base) io.netty.util.internal.PlatformDependent0 -> sun.misc.Unsafe internal (jdk.unsupported) io.netty.util.internal.UnsafeAtomicIntegerFieldUpdater -> sun.misc.Unsafe internal (jdk.unsupported) ... JDK Internal API Suggested Replacement ---------------- --------------------- sun.misc.BASE64Decoder Use java.util.Base64 @since 1.8 sun.misc.BASE64Encoder Use java.util.Base64 @since 1.8 sun.misc.Unsafe See http://openjdk.java.net/jeps/260 sun.security.x509.X500Name Use javax.security.auth.x500.X500Principal @since 1.4

Slide 33

Slide 33 text

Command line java/javac Override root modules configuration --add-modules module to add root modules --upgrade-module-path to replace some root modules Patch a module --patch-module module=files patch existing classes of a module Add a dependency (can be done by reflection too) --add-reads module=anotherModule Break encapsulation / allow setAccessible --add-exports module/package=anotherModule --add-opens modue/package=anotherModule

Slide 34

Slide 34 text

Restricted export

Slide 35

Slide 35 text

With 3 Modules java.base org.objectweb.asm.* asm-6.jar module moduletools.main { requires moduletools.api: exports fr.umlv.moduletools.main; } fr.umlv.moduletools.main moduletools.main fr.umlv.moduletools.transform fr.umlv.moduletools.api moduletools.api java.compiler module moduletools.api { requires moduletools.impl; exports fr.umlv.moduletools.api; } moduletools.impl fr.umlv.moduletools.internal module moduletools.impl { requires java.compiler: requires asm; exports fr.umlv.moduletools.internal; }

Slide 36

Slide 36 text

Restricted export An exported package can be restricted to a set of modules java.base org.objectweb.asm.* asm-6.jar fr.umlv.moduletools.api moduletools.api java.compiler module moduletools.api { requires moduletools.impl; exports fr.umlv.moduletools.api; } moduletools.impl fr.umlv.moduletools.internal module moduletools.impl { requires java.compiler: requires asm; exports fr.umlv.moduletools.internal to moduletools.api; }

Slide 37

Slide 37 text

sun.misc.Unsafe in 9 ? $ javap -m java.base module-info module java.base { …, exports sun.misc; exports jdk.internal.misc to java.rmi, java.sql, jdk.charsets, … } $ javap -m jdk.unsupported module-info module jdk.unsupported { exports sun.misc; } Keep sun.misc in 9, remove features when a public replacement APIs exist New internal unsafe API (hidden)

Slide 38

Slide 38 text

Module Service

Slide 39

Slide 39 text

Module Service Want to decouple the interface ModuleInput (resp. ModuleOutput) from its implementations Moduletools.api – fr.umlv.moduletools.api ● ModuleInput.java – static List availableInputs(); ● ClassModuleInput.java ● SourceModuleInput.java API Implementations

Slide 40

Slide 40 text

Module Service / Code package fr.umlv.moduletools.api; public interface ModuleInput { Optionial read(String name); } package fr.umlv.moduletools.api; … public interface ModuleInput { public static List availableInputs() { return ServiceLoader.load(ModuleInput.class).stream() ...; } } package fr.umlv.dragon.eval; public class InterpreterImpl implements Interpreter { … } interface an implementation usage

Slide 41

Slide 41 text

Uses / Provides … with java.base org.objectweb.asm.* asm-6.jar module moduletools.main { … } moduletools.main fr.umlv.moduletools.api moduletools.api java.compiler module moduletools.api { exports fr.umlv.moduletools.api; uses ... .api.ModuleInput; } moduletools.impl fr.umlv.moduletools.internal module moduletools.impl { requires java.compiler: requires asm; exports fr.umlv.moduletools.internal to moduletools.service; } module moduletools.service { requires moduletools.api; requires moduletools.impl; provides … .api.ModuleInput with … .service.SouceModuleInput; } fr.umlv.moduletools.service moduletools.service

Slide 42

Slide 42 text

Going Native !

Slide 43

Slide 43 text

jlink Create a custom runtime image from a set of root modules Image is specific for a platform Intel 64bits Linux, ARM 32bits Windows, etc For small devices or in the cloud (jlink is not mandatory !)

Slide 44

Slide 44 text

jlink and automatic module ! $ jlink --module-path $JAVA_HOME/jmods: \ target/main/artifact: \ deps \ --add-modules moduletools.main, \ moduletools.service \ --output image Error: jdk.tools.jlink.plugin.PluginException : module-info.class not found for asm module Automatic modules can see classes from the classpath so the world in not closed :(

Slide 45

Slide 45 text

jlink launcher In fact, ASM 6 is already a jigsaw module – so it works ! $ rm -fr image $ jlink --module-path $JAVA_HOME/jmods: \ target/main/artifact: \ deps \ --add-modules moduletools.main, \ moduletools.service \ --strip-debug \ --launcher moduletools=moduletools.main \ --output image

Slide 46

Slide 46 text

jlink image - Run moduletools $ ls -R image image: bin conf lib release image/bin: moduletools java keytool image/lib: amd64 classlist jexec modules security tzdb.dat … image/lib/amd64/server: classes.jsa libjsig.so libjvm.so Xusage.txt Run the executable $ ./image/bin/moduletools Run with the 'java' wrapper $ ./image/bin/java -m moduletools.main

Slide 47

Slide 47 text

Minimal VM On small device, use the minimal VM, $ jlink --module-path $JAVA_HOME/jmods: \ target/main/artifact:deps \ --add-modules moduletools.main, \ moduletools.service \ --strip-debug \ --launcher moduletools=moduletools.main \ --vm=minimal \ --output image size of the classical VM: 20 megs size of the minimal VM: 3 megs

Slide 48

Slide 48 text

Ahead Of Time compilation experimental feature ! Create a shared library (.so, .dll, .dynlib) from a module 2 modes – Non-tiered-mode: use AOT libs + interpreter – tiered-mode: use AOT libs + interpreter + JIT $ jaotc --module-path target/main/artifact --module moduletools.main

Slide 49

Slide 49 text

Ahead Of Time compilation experimental feature ! On disk $ ls lib/ libasm.all.so libjdk.compiler.so libmoduletools.impl.so libmoduletools.service.so libjava.base.so libmoduletools.api.so libmoduletools.main.so Run in AOT mode ./target/image/bin/java \ -XX:+UseAOT \ -XX:AOTLibrary=./lib/libjava.base.so \ -XX:AOTLibrary=./lib/libasm.all.so \ -XX:AOTLibrary=./lib/libmoduletools.impl.so \ -XX:AOTLibrary=./lib/libmoduletools.api.so \ -XX:AOTLibrary=./lib/libmoduletools.service.so \ -XX:AOTLibrary=./lib/libmoduletools.main.so \ -m moduletools.main/fr.umlv.moduletools.main.Main \ ...

Slide 50

Slide 50 text

BenchMarks !

Slide 51

Slide 51 text

Time to run moduletools

Slide 52

Slide 52 text

Size on disc

Slide 53

Slide 53 text

Jigsaw Goals Reliable configuration – No classpath anymore – compile time / runtime fidelity Scale down the platform – downsized unit of re-use Strong encapsulation – Separate public types from implementation – Enhanced security Closed World – Ahead of time optimizations

Slide 54

Slide 54 text

Questions ? Code is available at https://github.com/forax/moduletools