$30 off During Our Annual Pro Sale. View Details »

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

    View Slide

  2. FenixEdu

    View Slide

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

    View Slide

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

    View Slide

  5. JDK 9

    View Slide

  6. 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)

    View Slide

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

    View Slide

  8. JDK APIs

    View Slide

  9. ● 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

    View Slide

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

    View Slide

  11. 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!

    View Slide

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

    View Slide

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

    View Slide

  14. http://alexanderskoog.deviantart.com/

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  18. Jigsaw

    View Slide

  19. 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)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  30. // 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

    View Slide

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

    View Slide

  32. 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;
    }

    View Slide

  33. 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!

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  37. Application Migration

    View Slide

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

    View Slide

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

    View Slide

  40. Migration Strategies

    View Slide

  41. Top Down

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  49. Bottom Up
    or ‘How to migrate your library’

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  57. 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/

    View Slide

  58. Thank you!

    View Slide