Slide 1

Slide 1 text

Jigsaw - The Modular JDK PT.JUG - 03/12/2015 João Carvalho johnkarva jcarvalho Sérgio Silva sergiofbsilva sergiofbsilva

Slide 2

Slide 2 text

FenixEdu

Slide 3

Slide 3 text

Agenda What’s new in JDK 9? Project Jigsaw How can I prepare my application?

Slide 4

Slide 4 text

Disclaimer Most of the information shown in this presentation is based on multiple talks in JavaOne 2015 and Devoxx BE 2015. This presentation is focused on features that are under active development, and as such, a lot can change before the final release.

Slide 5

Slide 5 text

JDK 9

Slide 6

Slide 6 text

JDK 9 Flexibility and scalability Security and maintainability improvements Easing the construction, maintainability, deployment and upgrade of large scale applications Enabling performance improvements Coming to you, March 2017 (postponed on Tuesday)

Slide 7

Slide 7 text

JDK 9 Highlights ● VarHandles (JEP 193) ● The Modular JDK* (JEP 200) ● Modular Source Code (JEP 201) ● Modular Run-Time Images (JEP 220) ● jshell (JEP 222) ● New Version-String (JEP 223) ● UTF-8 Property Files (JEP 226) ● Multi-Release JAR Files (JEP 238) ● Cross-Release Compilation (JEP 247) ● Make G1 the default GC (JEP 248) * = Not yet targeted ● Compact Strings (JEP 254) ● Stack-Walking API (JEP 259) ● Encapsulate Most Internal APIs* (JEP 260) ● Module System* (JEP 261) ● Factory Methods for Collections (JEP 269) ● Dynamic Linking (JEP 276) ● Enhanced Deprecation* (JEP 277) ● Indify String Concatenation* (JEP 280)

Slide 8

Slide 8 text

JDK APIs

Slide 9

Slide 9 text

● Supported: ○ JCP Standard: java.*, javax.* ○ JDK-Specific: com.sun.*, some jdk.* ● Unsupported: ○ JDK Internal: sun.* ● Public, Supported APIs are generally backwards-compatible Categories of APIs on the JDK

Slide 10

Slide 10 text

Breaking APIs Judge risk and impact Good communication Provide replacement APIs or workarounds Provide upgrade paths and guides

Slide 11

Slide 11 text

Incompatible JDK 9 Changes ● Encapsulate most internal APIs (JEP 260) ● Remove the JRE ● Changing the binary structure of the JDK ● Removed endorsed standards override and extension mechanisms ● Removed bootclasspath ● New version-string format ● No more ‘_’ variables!

Slide 12

Slide 12 text

Most used JDK-internal APIs ● sun.misc.BASE64Encoder ● sun.misc.BASE64Decoder ● sun.misc.Unsafe ● sun.reflect.* ● com.sun.image.* ● sun.security.* ● sun.net.* ● Non-critical ○ Only used internally ○ Used for convenience ● Critical ○ Difficult to implement outside the JDK

Slide 13

Slide 13 text

JEP 260 ● Encapsulate non-critical APIs ● Encapsulate critical internal APIs with replacements in 8 ● Do not encapsulate critical APIs ○ Deprecate in 9 ○ Plan to remove in 10 ● sun.misc.Unsafe ● sun.misc.Signal ● sun.misc.SignalHandler ● sun.misc.Cleaner ● sun.reflect.Reflection:: getCallerClass ● sun.reflect.ReflectionFactory

Slide 14

Slide 14 text

http://alexanderskoog.deviantart.com/

Slide 15

Slide 15 text

-XaddExports -XaddExports:java.base/sun.security=ALL_UNNAMED

Slide 16

Slide 16 text

-XaddExports -XaddExports:java.base/sun.security=ALL_UNNAMED Module Package Target

Slide 17

Slide 17 text

What can I do to prepare? Remove usages of JDK-internal APIs Check for code that relies on the JDK version number format Check for usages of underscore as an identifier Test your code with the early access builds

Slide 18

Slide 18 text

Jigsaw

Slide 19

Slide 19 text

Why Jigsaw ? ● JAR/Classpath Hell ○ unfulfilled dependencies will only be discovered at runtime. NoClassDefFoundError ● Weak Encapsulation Across Packages ○ Across package boundaries there is only one visibility: public ○ class loader folds all loaded packages into one big ball of mud ■ “jar file is a filesystem on a stick” - Mark Reinhold (lead Jigsaw Oracle developer)

Slide 20

Slide 20 text

Why Jigsaw ? ● Rigid Java Runtime ○ Java8 introduced compact profiles but are still cluttered ○ large runtime image footprint (not ready for IoT and server containers) ● Startup Performance ○ class loading executes a linear scan of all JARs on the class path

Slide 21

Slide 21 text

Jigsaw - What gives ? The jdk9 itself built using modules ● Reliable Configuration ○ module/classes dependency graph available at any time (even runtime) ● Strong Encapsulation ○ A class that is private to a module should be private in exactly the same way that a private field is private to a class. In other words, module boundaries should determine not just the visibility of classes and interfaces but also their accessibility.

Slide 22

Slide 22 text

Jigsaw - What gives ? ● Improved Security And Maintainability ○ strong encapsulation of module internal API ○ critical code is now effectively hidden ○ maintenance easier as a module’s public API can more easily be kept small. ● Improved Performance ○ optimization techniques can be more effective when it is known that a class can refer only to classes in a few other specific components rather than to any class loaded at run time ● Scalable Platform ○ cherry pick the functionality needed and create their own JDK ○ important for small devices as well as for containers

Slide 23

Slide 23 text

Jigsaw - What is a Module ? ● Each module must declare ○ Which packages it exports ○ Which modules it requires ○ Implicit requires module java.base

Slide 24

Slide 24 text

Jigsaw - What is a Module ? org.fenixedu.foo.alpha.Alpha org.fenixedu.foo.alpha.AlphaFactory org.fenixedu.foo.alpha.AlphaService org.fenixedu.foo.beta.Beta org.fenixedu.foo.beta.BetaFactory org.fenixedu.foo.beta.BetaService org.fenixedu.foo.internal.GreekUtil fenixedu-foo.jar

Slide 25

Slide 25 text

Jigsaw - What is a Module ? org.fenixedu.foo.alpha.Alpha org.fenixedu.foo.alpha.AlphaFactory org.fenixedu.foo.alpha.AlphaService org.fenixedu.foo.beta.Beta org.fenixedu.foo.beta.BetaFactory org.fenixedu.foo.beta.BetaService org.fenixedu.foo.internal.GreekUtil fenixedu-foo.jar ├── org └── fenixedu └── foo ├── alpha │ ├── Alpha.java │ ├── AlphaFactory.java │ └── AlphaService.java ├── beta │ ├── Beta.java │ ├── BetaFactory.java │ └── BetaService.java └── internal └── GreekUtil.java public classes in a jar file

Slide 26

Slide 26 text

Jigsaw - Create a module org.fenixedu.foo.alpha.Alpha org.fenixedu.foo.alpha.AlphaFactory org.fenixedu.foo.alpha.AlphaService org.fenixedu.foo.beta.Beta org.fenixedu.foo.beta.BetaFactory org.fenixedu.foo.beta.BetaService org.fenixedu.foo.internal.GreekUtil org.fenixedu.foo // module-info.java module org.fenixedu.foo { // requires java.base; exports org.fenixedu.foo.alpha; exports org.fenixedu.foo.beta; } ├── module-info.java └── org └── fenixedu └── foo ├── alpha │ ├── Alpha.java │ ├── AlphaFactory.java │ └── AlphaService.java ├── beta │ ├── Beta.java │ ├── BetaFactory.java │ └── BetaService.java └── internal └── GreekUtil.java

Slide 27

Slide 27 text

Jigsaw - Create a module # compiling module > javac -d mods/org.fenixedu.foo $(find org.fenixedu.foo/src -name '*. java') # package module as a module jar file > jar --create --file mlib/foo.jar -C mods/org.fenixedu.foo .

Slide 28

Slide 28 text

Jigsaw - Create a module # listing jar files > jar tvf mlib/foo.jar META-INF/ META-INF/MANIFEST.MF module-info.class org/ org/fenixedu/ org/fenixedu/foo/ org/fenixedu/foo/alpha/ org/fenixedu/foo/alpha/Alpha.class org/fenixedu/foo/alpha/AlphaFactory.class org/fenixedu/foo/alpha/AlphaService.class org/fenixedu/foo/beta/ org/fenixedu/foo/beta/Beta.class org/fenixedu/foo/beta/BetaFactory.class org/fenixedu/foo/beta/BetaService.class org/fenixedu/foo/internal/ org/fenixedu/foo/internal/GreekUtil.class

Slide 29

Slide 29 text

Jigsaw - Create a module # --print-module-descriptor > jar -f mlib/foo.jar -p Name: org.fenixedu.foo Requires: java.base [ MANDATED ] Exports: org.fenixedu.foo.alpha org.fenixedu.foo.beta Conceals: org.fenixedu.foo.internal # listing jar files > jar tvf mlib/foo.jar META-INF/ META-INF/MANIFEST.MF module-info.class org/ org/fenixedu/ org/fenixedu/foo/ org/fenixedu/foo/alpha/ org/fenixedu/foo/alpha/Alpha.class org/fenixedu/foo/alpha/AlphaFactory.class org/fenixedu/foo/alpha/AlphaService.class org/fenixedu/foo/beta/ org/fenixedu/foo/beta/Beta.class org/fenixedu/foo/beta/BetaFactory.class org/fenixedu/foo/beta/BetaService.class org/fenixedu/foo/internal/ org/fenixedu/foo/internal/GreekUtil.class

Slide 30

Slide 30 text

// org/fenixedu/bar/gamma/Gamma.java package org.fenixedu.bar.gamma; import org.fenixedu.foo.alpha.Alpha; public class Gamma { public static void main(String...args) { Alpha alpha = new Alpha(); System.out.println( "I am gamma!" ); } } org.fenixedu.bar.gamma.Gamma org.fenixedu.bar.gamma.GammaFactory org.fenixedu.bar.gamma.GammaService org.fenixedu.bar.internal.GreekUtil fenixedu-bar.jar Jigsaw - Module Dependency

Slide 31

Slide 31 text

Jigsaw - Module Dependency org.fenixedu.foo.alpha.Alpha org.fenixedu.foo.alpha.AlphaFactory org.fenixedu.foo.alpha.AlphaService org.fenixedu.foo.beta.Beta org.fenixedu.foo.beta.BetaFactory org.fenixedu.foo.beta.BetaService org.fenixedu.foo.internal.GreekUtil fenixedu-foo.jar org.fenixedu.bar.gamma.Gamma org.fenixedu.bar.gamma.GammaFactory org.fenixedu.bar.gamma.GammaService org.fenixedu.bar.internal.GreekUtil fenixedu-bar.jar Gamma imports Alpha

Slide 32

Slide 32 text

Jigsaw - Module Dependency ├── module-info.java └── org └── fenixedu └── bar ├── gamma │ ├── Gamma.java │ ├── GammaFactory.java │ └── GammaService.java └── internal └── GreekUtil.java org.fenixedu.bar.gamma.Gamma org.fenixedu.bar.gamma.GammaFactory org.fenixedu.bar.gamma.GammaService org.fenixedu.bar.internal.GreekUtil fenixedu-bar.jar // module-info.java module org.fenixedu.bar { // requires java.base; requires org.fenixedu.foo; }

Slide 33

Slide 33 text

Jigsaw - Running a module > javac -modulepath mods/ -d mods/org.fenixedu.bar $(find org.fenixedu.bar/src -name '*.java') > jar --create --file mlib/bar.jar --main-class org.fenixedu.bar.gamma.Gamma -C mods/org.fenixedu.bar . > jar -f mlib/bar.jar -p Name: org.fenixedu.bar Requires: org.fenixedu.foo java.base [ MANDATED ] Main class: org.fenixedu.bar.gamma.Gamma Conceals: org.fenixedu.bar.gamma org.fenixedu.bar.internal > java -mp mlib -m org.fenixedu.bar I am gamma!

Slide 34

Slide 34 text

Jigsaw - Module dependencies > jdeps -s mlib/bar.jar mlib/foo.jar bar.jar -> mlib/foo.jar bar.jar -> java.base foo.jar -> java.base

Slide 35

Slide 35 text

Jigsaw - Module dependencies > jdeps -dotoutput . mlib/bar.jar mlib/foo.jar

Slide 36

Slide 36 text

Jigsaw - Modular Runtime Images (JEP 200) ● Create a custom jdk image with only the necessary modules > jlink --modulepath $JDKMODS:mlib --addmods org.fenixedu.bar --output myimage > myimage/bin/java -listmods [email protected] org.fenixedu.bar org.fenixedu.foo

Slide 37

Slide 37 text

Application Migration

Slide 38

Slide 38 text

Typical Application JDK JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR JAR

Slide 39

Slide 39 text

Sample Application JDK jackson- annotations.jar jackson- databind.jar jackson-core.jar bar.jar foo.jar

Slide 40

Slide 40 text

Migration Strategies

Slide 41

Slide 41 text

Top Down

Slide 42

Slide 42 text

Sample Application JDK jackson- annotations.jar jackson- databind.jar jackson-core.jar bar.jar foo.jar

Slide 43

Slide 43 text

Sample Application module java.base jackson-core.jar jackson- databind.jar jackson- annotations.jar module bar module foo module java.logging module java.sql module java.xml

Slide 44

Slide 44 text

Automatic Modules “Real” modules Module name based on JAR file name (with some dark wizardry) Simply move the non-modular JARs from the classpath to the modulepath Exports all packages Requires all modules on the modulepath

Slide 45

Slide 45 text

Sample Application // src/bar/module-info.java module org.fenixedu.bar { requires org.fenixedu.foo; }

Slide 46

Slide 46 text

Sample Application // src/bar/module-info.java module org.fenixedu.bar { requires org.fenixedu.foo; ?? requires jackson-core.jar ?? ?? requires jackson-databind.jar ?? }

Slide 47

Slide 47 text

Sample Application // src/bar/module-info.java module org.fenixedu.bar { requires org.fenixedu.foo; requires jackson.core; requires jackson.databind; }

Slide 48

Slide 48 text

Automatic Modules module java.base module jackson.core module jackson.databind module jackson.annotations module bar module foo module java.logging module java.sql module java.xml

Slide 49

Slide 49 text

Bottom Up or ‘How to migrate your library’

Slide 50

Slide 50 text

Bottom Up Migration JDK jackson- annotations.jar jackson- databind.jar jackson-core.jar bar.jar foo.jar

Slide 51

Slide 51 text

Bottom Up Migration module java.base bar.jar foo.jar module java.logging module java.sql module java.xml module jackson.core module jackson.databind module jackson.annotations

Slide 52

Slide 52 text

Bottom Up Migration $ java -mp mlib -cp lib/foo.jar:lib/bar.jar -addmods jackson.databind org. fenixedu.bar.gamma.Gamma Exception in thread "main" java.lang.reflect. InaccessibleObjectException: Unable to make member of class org.fenixedu.bar.gamma.Gamma accessible: module jackson.databind does not read

Slide 53

Slide 53 text

Unnamed Module All non-modular JARs in the classpath are added to the ‘Unnamed Module’ Reads all other modules in the application Exports all its packages Real modules are not allowed to explicitly depend on the unnamed module Read-node may be added in runtime via reflection

Slide 54

Slide 54 text

Unnamed Module package java.lang.reflect; public final class Module { public String getName(); public boolean canRead(Module source); public Module addReads(Module source); ... }

Slide 55

Slide 55 text

Unnamed Module Module source = clazz.getModule(); this.getClass().getModule().addReads(source);

Slide 56

Slide 56 text

Go forth and modularize! Download the Jigsaw Early-Access build http://openjdk.java.net/projects/jigsaw/ea Try out this presentation code https://github.com/sergiofbsilva/jigsaw

Slide 57

Slide 57 text

Links http://openjdk.java.net/projects/jigsaw/ http://openjdk.java.net/projects/jigsaw/talks/ http://mail.openjdk.java.net/mailman/listinfo/jigsaw-dev http://openjdk.java.net/projects/jdk9/

Slide 58

Slide 58 text

Thank you!