Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Jigsaw - The Modular JDK

Jigsaw - The Modular JDK

This is the talk we gave at PT.JUG's 23rd meetup, about the JDK 9 and Jigsaw.

João Carvalho

December 03, 2015
Tweet

More Decks by João Carvalho

Other Decks in Programming

Transcript

  1. Jigsaw - The Modular JDK PT.JUG - 03/12/2015 João Carvalho

    johnkarva jcarvalho Sérgio Silva sergiofbsilva sergiofbsilva
  2. 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.
  3. 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)
  4. 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)
  5. • 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
  6. Breaking APIs Judge risk and impact Good communication Provide replacement

    APIs or workarounds Provide upgrade paths and guides
  7. 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!
  8. 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
  9. 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
  10. 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
  11. 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)
  12. 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
  13. 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.
  14. 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
  15. Jigsaw - What is a Module ? • Each module

    must declare ◦ Which packages it exports ◦ Which modules it requires ◦ Implicit requires module java.base
  16. 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
  17. 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
  18. 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
  19. 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 .
  20. 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
  21. 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
  22. // 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
  23. 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
  24. 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; }
  25. 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!
  26. Jigsaw - Module dependencies > jdeps -s mlib/bar.jar mlib/foo.jar bar.jar

    -> mlib/foo.jar bar.jar -> java.base foo.jar -> java.base
  27. 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
  28. 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
  29. 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
  30. Sample Application // src/bar/module-info.java module org.fenixedu.bar { requires org.fenixedu.foo; ??

    requires jackson-core.jar ?? ?? requires jackson-databind.jar ?? }
  31. 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
  32. 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
  33. 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 <unnamed module @b8623654>
  34. 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
  35. Unnamed Module package java.lang.reflect; public final class Module { public

    String getName(); public boolean canRead(Module source); public Module addReads(Module source); ... }
  36. 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