Save 37% off PRO during our Black Friday Sale! »

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.

Eb987f4f2b2d43faa8b3b5a377713913?s=128

João Carvalho

December 03, 2015
Tweet

Transcript

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

    johnkarva jcarvalho Sérgio Silva sergiofbsilva sergiofbsilva
  2. FenixEdu

  3. Agenda What’s new in JDK 9? Project Jigsaw How can

    I prepare my application?
  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.
  5. JDK 9

  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)
  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)
  8. JDK APIs

  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
  10. Breaking APIs Judge risk and impact Good communication Provide replacement

    APIs or workarounds Provide upgrade paths and guides
  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!
  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
  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
  14. http://alexanderskoog.deviantart.com/

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

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

  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
  18. Jigsaw

  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)
  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
  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.
  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
  23. Jigsaw - What is a Module ? • Each module

    must declare ◦ Which packages it exports ◦ Which modules it requires ◦ Implicit requires module java.base
  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
  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
  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
  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 .
  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
  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
  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
  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
  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; }
  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!
  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
  35. Jigsaw - Module dependencies > jdeps -dotoutput . mlib/bar.jar mlib/foo.jar

  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 java.base@9.0 org.fenixedu.bar org.fenixedu.foo
  37. Application Migration

  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
  39. Sample Application JDK jackson- annotations.jar jackson- databind.jar jackson-core.jar bar.jar foo.jar

  40. Migration Strategies

  41. Top Down

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

  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
  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
  45. Sample Application // src/bar/module-info.java module org.fenixedu.bar { requires org.fenixedu.foo; }

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

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

    jackson.core; requires jackson.databind; }
  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
  49. Bottom Up or ‘How to migrate your library’

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

    foo.jar
  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
  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 <unnamed module @b8623654>
  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
  54. Unnamed Module package java.lang.reflect; public final class Module { public

    String getName(); public boolean canRead(Module source); public Module addReads(Module source); ... }
  55. Unnamed Module Module source = clazz.getModule(); this.getClass().getModule().addReads(source);

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

  58. Thank you!