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

Workshop - Java 9 – Das neue Modulsystem Jigsaw

Workshop - Java 9 – Das neue Modulsystem Jigsaw

Martin Lehmann, Kristine Schaal, Rüdiger Grammes: „Java 9 – Das neue Modulsystem Jigsaw“. IT-Tage 2017, Frankfurt, Workshoptag, 11. Dezember 2017

Martin Lehmann

December 11, 2017
Tweet

More Decks by Martin Lehmann

Other Decks in Programming

Transcript

  1. t 11. – 14.12.2017 Frankfurt am Main Java 9 –

    Das neue Modulsystem Jigsaw Dr. Rüdiger Grammes, Martin Lehmann, Dr. Kristine Schaal #ittage
  2. Copyright © Accso – Accelerated Solutions GmbH 2 v.3 2

    v.3.12 Java 9 - Das neue Modulsystem Jigsaw DR. RÜDIGER GRAMMES, MARTIN LEHMANN, DR. KRISTINE SCHAAL | IT-TAGE 2017 IT-Tage 2017, Dezember 2017
  3. Copyright © Accso – Accelerated Solutions GmbH 3 Mit Java

    9 kommt das lange angekündigte Modulsystem Jigsaw. Jigsaw ist eine grundlegende Strukturänderung von Java-Plattform und -Sprache, mit deren Auswirkungen man sich möglichst früh beschäftigen sollte. In diesem Tutorial erläutern wir Grundlagen von Jigsaw. Wir zeigen Motive und Ziele für die Einführung eines Modulsystems. Anhand von Code-Beispielen lernen die Teilnehmer, wie das Modulsystem aussieht und welche wichtigen Designentscheidungen getroffen wurden: • Warum braucht Java überhaupt ein Modulsystem? • Was will man erreichen? • Wie profitieren Entwickler davon? • Was ist ein Modul? • Wie definiere ich Module und Abhängigkeiten? • Welche Sichtbarkeiten gibt es zwischen Modulen? • Module sind sowohl Compiler-Erweiterung als auch Teil des Laufzeitsystems. Wie wirkt sich das aus? • Wie vertragen sich Module mit generischen Ansätzen wie Reflection oder Callbacks, auf denen eine Reihe bekannter Frameworks basieren? • Welche anderen Konstrukte gibt es (Beispiel: Services)? • Wie sehen Tools aus? • IDE? • Build-/Dependency-Management? Wir bieten diese Einführung als Tutorial in Form eines interaktiven Entwicklerworkshops an. Wir zeigen die Grundlagen mit Folien und führen interaktiv durch Beispiele und Code, u.a. zu Module-Info, requires, exports, uses/provides, Interface/Implementierung, Exceptions, Reflection, Module-API und - Finder usw. Alle Beispiele können die Teilnehmer selbst auf ihrem Laptop mitmachen und somit alles lokal nachvollziehen. Sourcecode und SEU/Entwicklungsumgebung mit JDK, Eclipse stellen wir zur Verfügung. Abstract IT-Tage 2017 https://www.ittage.informatik-aktuell.de/programm/2017/java-9-das-neue-modulsystem-jigsaw/
  4. Copyright © Accso – Accelerated Solutions GmbH 4 Dr. Rüdiger

    Grammes, Accso - Accelerated Solutions GmbH Softwarearchitekt Dr. Rüdiger Grammes ist seit November 2011 als Principal bei der Accso – Accelerated Solutions GmbH und dort als Softwarearchitekt in verschiedenen Projekten unterwegs. [email protected] www.xing.com/profile/Ruediger_Grammes Martin Lehmann, Accso - Accelerated Solutions GmbH Cheftechnologe Martin Lehmann ist Diplom-Informatiker und arbeitet als Cheftechnologe und Softwarearchitekt bei der Accso - Accelerated Solutions GmbH. Seit Ende der 90er-Jahre wirkt er als Softwareentwickler und -architekt in der Softwareentwicklung in diversen Projekten der Individualentwicklung für Kunden verschiedener Branchen. Seit den Zeiten von Java 1.0 beschäftigt er sich mit Java als Programmiersprache und als Ökosystem. [email protected] @lemmi111171 www.xing.com/profile/Martin_Lehmann3 Dr. Kristine Schaal, Accso - Accelerated Solutions GmbH Softwarearchitektin Dr. Kristine Schaal ist als Softwarearchitektin bei der Accso - Accelerated Solutions GmbH tätig. Sie arbeitet seit fast 20 Jahren in der Softwareentwicklung und ist in Projekten der Individualentwicklung für Kunden verschiedener Branchen unterwegs, technisch überwiegend im Java-Umfeld. [email protected] @krschaal www.xing.com/profile/Kristine_Schaal
  5. Copyright © Accso – Accelerated Solutions GmbH 6 alter JSR

    277 (2005-2016) „Java Module System“ alter JSR 294 (2006-2016) „Improved Modularity Support” alter JSR 291 (2006-2007) „Dynamic Component Support“
  6. Copyright © Accso – Accelerated Solutions GmbH 7 Project Jigsaw:

    JSR 376 und seine Ziele Strong Encapsulation Eine Komponente kann ihr öffentliches API definieren und den Zugriff auf Implementierungsgeheimnisse verhindern. Reliable Configuration Ablösung des Classpath (fehleranfällig, wenn Klassen mehrfach enthalten sind  Reihenfolge). Scalable Java SE Platform Die Java-Plattform selber ist nun modularisiert. Man kann individuell angepasste, „schlanke“ Plattformen bauen. JSR 376 (2014-2017) „Java Platform Module System“ (JPMS) Project Jigsaw in Java 9-Release vom 21. September 2017 enthalten. Aktuell: 9.0.1 vom 18. Oktober 2017 Enthalten: JEP 261, 200, 201, 220, 260, 282 mit Modulsystem, modularisiertem JDK und der Kapselung interner APIs
  7. Copyright © Accso – Accelerated Solutions GmbH 10 Modul :=

    Menge von Java-Packages & Resources Wird in ein „Modular JAR“ kompiliert. Dieses liegt im neuen Module-Path MP. Modul-Namen müssen eindeutig sein (erlaubt sind . und _ , aber nicht -) • „read“-Abhängigkeitsbeziehungen zu einem oder mehreren anderen Modulen • „exports“: Welche Packages des Moduls werden exportiert? (Default: nichts!) modmain Ein Modul ist ab Java 9 ein „First-Class-Citizen“ in Java. moda read exports pkg main pkg a pkga inter nal
  8. Copyright © Accso – Accelerated Solutions GmbH 15 Neu in

    Java 9: Readability und Accessibility read modmain pkg main Checks zu Compile-Zeit und zur Laufzeit von 1. neu: Readability „ich benötige dieses Modul, will darauf zugreifen“ 2. neu: Accessibility „worauf dürfen andere zugreifen?“ (unabhg. von Classloadern!) 3. Check der „alten“ Sichtbarkeitsmodifier public,protected,<package>,private de.my. package. ximpl de.my. package. internal de.my. package exports moda
  9. Copyright © Accso – Accelerated Solutions GmbH 16 Beispiel: Vier

    Module moda, modb, modc, modmain und ihr Sourcenbaum moda/ module-info.java pkga1/ A1.java pkga2/ A2.java pkga3/ A3.java pkgainternal/ InternalA.java modb/ module-info.java pkgb/ B.java modc/ module-info.java pkgc/ C.java modmain/ module-info.java pkgmain/ Main.java
  10. Copyright © Accso – Accelerated Solutions GmbH 17 moda/ module-info.java

    pkga1/ A1.java pkga2/ A2.java pkga3/ A3.java pkgainternal/ InternalA.java modb/ module-info.java pkgb/ B.java modc/ module-info.java pkgc/ C.java modmain/ module-info.java pkgmain/ Main.java Modul-Definition eines Moduls liegt in Datei module-info.java im obersten Modul-Sourcenverzeichnis. • mit allen die Abhängigkeiten zu anderen Modulen • mit der Liste der zugreifbaren Packages Wird kompiliert zu .class-File! Wird mit in das JAR-File paketiert. Beispiel: Vier Module moda, modb, modc, modmain und ihr Sourcenbaum module-info.java
  11. Copyright © Accso – Accelerated Solutions GmbH 19 Abhängigkeitsbeziehungen der

    Module moda, modb, modc, modmain moda/ module-info.java pkga1/ A1.java pkga2/ A2.java pkga3/ A3.java pkgainternal/ InternalA.java modb/ module-info.java pkgb/ B.java modc/ module-info.java pkgc/ C.java modmain/ module-info.java pkgmain/ Main.java module-info.java
  12. Copyright © Accso – Accelerated Solutions GmbH 20 module moda

    { // Read-Abhängigkeiten von moda zu modb und modc // (Compiler meckert fehlende Module an!) requires modb; requires transitive modc; // immer dabei: Abhängigkeit zu java.base // (mandated) // requires java.base; } moda/ module-info.java pkga1/ A1.java pkga2/ A2.java pkga3/ A3.java pkgainternal/ InternalA.java modb/ module-info.java pkgb/ B.java modc/ module-info.java pkgc/ C.java modmain/ module-info.java pkgmain/ Main.java module-info.java moda/module-info.java
  13. Copyright © Accso – Accelerated Solutions GmbH 21 requires transitive

    für transitive Abhängigkeiten module moda { requires modb; requires transitive modc; ...
  14. Copyright © Accso – Accelerated Solutions GmbH 22 requires static

    für optionale Abhängigkeiten module modmain { // Modul muss zur Compilezeit vorhanden sein // Zur Laufzeit ist das Modul optional requires static modb; } module modb { // requires static kann ebenfalls transitiv sein requires static transitive modc; } Optionale Abhängigkeiten werden zur Laufzeit nicht in den Modulgraph aufgenommen. Über den Launcher-Parameter --add-modules kann das Modul explizit aufgenommen werden.
  15. Copyright © Accso – Accelerated Solutions GmbH 24 Beispiel Schnittstelle

    java.sql.Driver Implementierung in Modul java.sql im MySQL-Driver Dynamische Bindung beim Start über ServiceLoader, also keine statische Auflösung über Modul-Namen wie bei Requires! Dynamische Bindung von Interface und Implementierung module java.sql { … // Definiert Schnittstelle uses java.sql.Driver; // ... und exportiert sie auch exports java.sql; } module com.mysql.jdbc { requires java.sql; … // Implementiert Schnittstelle provides java.sql.Driver with com.mysql.jdbc.Driver; }
  16. Copyright © Accso – Accelerated Solutions GmbH 26 Zugriffsschutz für

    Modul moda moda/ module-info.java pkga1/ A1.java pkga2/ A2.java pkga3/ A3.java pkgainternal/ InternalA.java modb/ module-info.java pkgb/ B.java modc/ module-info.java pkgc/ C.java modmain/ module-info.java pkgmain/ Main.java module-info.java
  17. Copyright © Accso – Accelerated Solutions GmbH 27 module moda

    { // Read-Abhängigkeiten von moda zu modb und modc // (Compiler meckert fehlende Module an!) requires modb; requires transitive modc; // Exports von Packages von moda // (Compiler meckert fehlende Packages an!) exports pkga1; exports pkga2 to modmain; // nur an modmain opens pkga3; // nur zur Laufzeit // für Reflection } moda/ module-info.java pkga1/ A1.java pkga2/ A2.java pkga3/ A3.java pkgainternal/ InternalA.java modb/ module-info.java pkgb/ B.java modc/ module-info.java pkgc/ C.java modmain/ module-info.java pkgmain/ Main.java module-info.java modmain moda/module-info.java
  18. Copyright © Accso – Accelerated Solutions GmbH 32 Zugriff auf

    eine Resource in einem anderen Modul moda: Kein Zugriff erlaubt? Stream ist null , keine IllegalAccessException Der Zugriff ist immer auch ohne opens möglich auf: • Resources im "unnamed package" • Resources, deren Verzeichnis sich nicht auf einen gültigen Packagenamen abbilden lässt (z.B. META-INF/MANIFEST.MF) Resource wird über ihr Verzeichnis geschützt, wenn sich dieses auf einen Package-Namen abbilden lässt. Das Package muss mit opens (nicht exports!) geöffnet sein. Der Zugriff auf Resources anderer Module ist geschützt! A.class.getModule().getResourceAsStream("/foo/bar.properties")
  19. Copyright © Accso – Accelerated Solutions GmbH 33 Wie steht‘s

    um Reflection? (und um Serialisierung, Dependency-Injection, Bytecode-Enhancement etc.) Zur Erinnerung 1. Check der Readability 2. Check der Accessibility 3. Check von public,protected,<package>,private Alle Checks auch bei Reflection! Convenience bei Reflection: read-Beziehung ist immer vorhanden. Aber Accessibility-Checks greifen auch „scharf“ bei Reflection: Klassen in nicht exportierten Packages sind also nicht zugreifbar. • Gilt für newInstance, getField, getMethod, … • Gilt auch für setAccessible(true)
  20. Copyright © Accso – Accelerated Solutions GmbH 34 opens öffnet

    für „Deep Reflection“ mit setAccessible(true) Shortcut „open module“ öffnet alle Packages des Moduls mit „opens“ opens öffnet ein Package nur zur Laufzeit Compile-Zeit Reflection (Shallow) Reflection (Deep) exports pkg erlaubt erlaubt nicht erlaubt opens pkg nicht erlaubt erlaubt erlaubt exports pkg und opens pkg erlaubt erlaubt erlaubt
  21. Copyright © Accso – Accelerated Solutions GmbH 35 Letztlich geht‘s

    immer um Typen-Sichtbarkeit: Interfaces exports pkga inter nal pkga Inte rnal Data Nur Export von IData Instanzen von InternalData behalten ihren Typ auch über Modulgrenze hinaus. public class Factory { public IData createData() { return new InternalData(); } … public class Caller { … IData myData = new Factory().createData(); … I Data Fact ory Call er mod main moda pkgmain
  22. Copyright © Accso – Accelerated Solutions GmbH 36 Letztlich geht‘s

    immer um Typen-Sichtbarkeit: Ableitung exports pkga inter nal pkga Inte rnal Data Nur Export von Data Instanzen von InternalData behalten ihren Typ auch über Modulgrenze hinaus. public class Factory { public Data createData() { return new InternalData(); } … public class Caller { … Data myData = new Factory().createData(); … Data Fact ory Call er moda mod main pkgmain
  23. Copyright © Accso – Accelerated Solutions GmbH 37 Letztlich geht‘s

    immer um Typen-Sichtbarkeit: Ableitung exports pkga inter nal pkga Inte rnal Data Caller kann nur Methoden von Data aufrufen, es werden aber die Implementierungen von InternalData benutzt. public class Factory { public Data createData() { return new InternalData(); } … public class Caller { … Data myData = new Factory().createData(); … Data Fact ory Call er moda mod main pkgmain
  24. Copyright © Accso – Accelerated Solutions GmbH 38 pkga inter

    nal pkga Letztlich geht‘s immer um Typen-Sichtbarkeit: Exceptions Interne Exceptions können nach außen geworfen werden. Caller kann nur Oberklassen fangen. public class A { public void doIt() throws InternalException { ... } public class Caller { … try { new A().doIt(); } catch(Exception ex) {...} catch(RuntimeException rex) {…} … Call er moda Inter nal Excep tion Inter nalRun timeExc eption exports A mod main pkgmain
  25. Copyright © Accso – Accelerated Solutions GmbH 42 Wenn Exports

    & Reads der module-info nicht reichen…? Neue Read-Beziehung vonnach Export/Open weiterer Packages Kommandozeile javac, java oder @file programmatisch --add-reads … java.lang. Module.addReads() --add-exports … --add-opens … java.lang. Module.addExports() Module.addOpens() Vorsicht - Caller-sensitiv: Aufruf nur im eigenen Modul möglich! Angabe im JAR-Manifest Add-Exports: … Add-Opens: …
  26. Copyright © Accso – Accelerated Solutions GmbH 44 Blackbox-Test testet

    nur öffentliche Schnittstelle von moda. Neues Modul braucht also keinen Zugriff auf interne Klassen. Blackbox-Test eines Moduls moda moda read exports pkga internal pkga $ java --module-path mlib\;amlib --add-modules modtest.blackbox -m junit/org.junit.runner.JUnitCore pkgblacktest.BlackBoxTest junit read modtest. blackbox pkg black test
  27. Copyright © Accso – Accelerated Solutions GmbH 45 Vier Varianten

    für Whitebox-Tests eines Moduls moda Ein Whitebox-Test benötigt zum Test interne Klassen von moda aus dem Package pkgainternal. moda pkga internal pkga Unschön Ein Patch des JAR-Files moda.jar mit passender module-info.class ist i.d.R. keine Alternative. Funktioniert z.B. nicht bei Checksummen! exports
  28. Copyright © Accso – Accelerated Solutions GmbH 46 1. Separates

    Test-Modul modtest.whitebox Wie erhält es Zugriff auf die internen Packages von moda? Whitebox-Test eines Moduls moda : Varianten 1a, b Statische Abhängigkeit zu Testcode Pflege der Skripte?! module moda { exports pkga; exports pkgainternal to modtest.whitebox; } a) Mit exports to der zu testenden Packages an modtest.whitebox $ javac --add-exports moda/pkgainternal=modtest.whitebox $ java --add-exports moda/pkgainternal=modtest.whitebox b) Dynamischer Export der zu testenden Packages mit --add-exports
  29. Copyright © Accso – Accelerated Solutions GmbH 47 2. Das

    Modul moda enthält auch die Testklassen. Aber wo verwaltet man diese? Whitebox-Test eines Moduls moda : Varianten 2a, b Testcode wird mit paketiert und deployed a) Testklassen sind Teil von moda. Testklassen können damit alle zu testenden Klassen aus moda sehen. b) Testklassen werden getrennt abgelegt. Zu Compile-Zeit und zur Test-Laufzeit werden sie dem Modul moda hinzugefügt („Patchen“).
  30. Copyright © Accso – Accelerated Solutions GmbH 48 Whitebox-Test Variante

    2b: moda beim Compile patchen moda pkga internal pkga $ javac --patch-module moda=testsrc --add-reads moda=junit -d patches/test/moda ... testsrc/modtest.whitebox/pkga/WhiteBoxTest.java junit pkga internal …Test
  31. Copyright © Accso – Accelerated Solutions GmbH 49 moda pkga

    internal pkga pkga internal …Test Whitebox-Test Variante 2b: moda bei Test-Start patchen $ java --patch-module moda=patches/test/moda --add-reads moda=junit ... -m junit/org.junit.runner.JUnitCore pkga.WhiteBoxTest junit
  32. Copyright © Accso – Accelerated Solutions GmbH 51 Observable Modules

    System-Module-Path Observable Modules: „Was da ist“ java. base Module-Path mlib modmain Alle Module auf dem Module-Path zusammen mit den System-Modulen bilden das „Universum“ der Observable Modules.
  33. Copyright © Accso – Accelerated Solutions GmbH 52 Die Configuration

    ist die transitive Hülle aller Abhängigkeiten aller Root-Module der Observable Modules. Root-Module ist hier modmain Observable Modules System-Module-Path Configuration: „Was wirklich geladen wird“ Module-Path mlib modmain java. base modmain java. base $ java --module-path mlib -m modmain/pkgmain.Main
  34. Copyright © Accso – Accelerated Solutions GmbH 53 Observable Modules

    System-Module-Path Configuration: Weitere Module dazunehmen Module-Path mlib modmain java. base modmain java. base modx Weitere Root-Module werden Configuration mitgegeben über --add-modules modx $ java --module-path mlib --add-modules modx -m modmain/pkgmain.Main
  35. Copyright © Accso – Accelerated Solutions GmbH 54 Observable Modules

    System-Module-Path Configuration: Alle Module aus Module-Path dazunehmen Module-Path mlib modmain java. base modmain java. base modx Shortcut für „alle Module aus MP“ dazunehmen über ALL-MODULE-PATH $ java --module-path mlib --add-modules ALL-MODULE-PATH -m modmain/pkgmain.Main
  36. Copyright © Accso – Accelerated Solutions GmbH 55 Ist ein

    Modul moda mehrfach auf dem Module-Path vorhanden, so wird nach Reihenfolge der Angabe eingezogen, hier im Beispiel aus mlib1 Keine Warning bei Inhalten bzw. Versionen! Observable Modules System-Module-Path Configuration: Vorsicht beim „Shadowing“ von Modulen Module-Path mlib1 modmain modmain Module-Path mlib2 moda java. base $ java --module-path mlib1;mlib2 -m modmain/pkgmain.Main moda moda
  37. Copyright © Accso – Accelerated Solutions GmbH 58 Compile Run

    Neue Argumente für Compiler und Launcher $ JAVA_HOME/bin/java --module-path mlib --module modmain/pkgmain.Main $ JAVA_HOME/bin/javac -d mods --module-path mlib --module-source-path src $(find src -name "*.java")
  38. Copyright © Accso – Accelerated Solutions GmbH 59 Modul auf

    dem MP Modul in einem JAR Modul in einer JMOD-Datei Aus einer module- info.class Wie kann man Informationen zu einem Modul ausgeben? $ jar --file mlib/moda.jar –-describe-module $ jdeps --module-path mlib mlib/moda.jar $ jmod describe $JAVA_HOME/jmods/java.base.jmod $ javap -verbose module-info.class $ java --module-path mlib --describe-module moda
  39. Copyright © Accso – Accelerated Solutions GmbH 60 keine Angabe

    in der module-info! Stattdessen kann eine Modul-Version beim Paketieren des JAR-Files mitgegeben werden! Wie setzt man die Modul-Version? $ jar --file ./mlib/moda.jar –-describe-module [email protected] jar:file:///…/mlib/moda.jar/!module-info.class exports pkga1 requires java.base mandated requires modb requires modc transitive qualified exports pkga2 to modmain opens pkga3 contains pkgainternal $ jar --create --module-version=47.11alpha3 --file=./mlib/moda.jar –C mods/moda
  40. Copyright © Accso – Accelerated Solutions GmbH 61 Wie generiert

    man module-info für „normales JAR“? $ jdeps --generate-module-info ./gensrc -s amlib/*.jar module junit { // Modul-Name "junit" automatisch aus junit-4.12.jar requires java.management; requires transitive hamcrest.core; exports junit.extensions; // es werden *alle* Packages exportiert exports junit.framework; exports junit.runner; exports junit.textui; exports org.junit; ... exports org.junit.runners.model; exports org.junit.runners.parameterized; exports org.junit.validator; } z.B. für JAR-File junit-4.12.jar
  41. Copyright © Accso – Accelerated Solutions GmbH 62 open module

    junit { // Modul-Name "junit" automatisch aus junit-4.12.jar requires java.management; requires transitive hamcrest.core; } $ jdeps --generate-open-module ./gensrc -s amlib/*.jar Wie generiert man module-info für „normales JAR“? z.B. für JAR-File junit-4.12.jar
  42. Copyright © Accso – Accelerated Solutions GmbH 63 Observable Modules

    Configuration Debugging Debugger gibt Modul aus Stacktrace gibt Modul mit aus Wie erhalte ich Informationen zur Laufzeit? $ java –Xdiag:resolver ... $ java –Xlog:module=debug|trace ... $ java --module-path ./mlib --list-modules ... über Class.getModule() pkgb.MyException: MyException's message at modb/pkgb.B.doItThrowException(B.java:13) at modmain/pkgmain.Main.main(Main.java:18) $ java --module-path ./mlib --show-module-resolution
  43. Copyright © Accso – Accelerated Solutions GmbH 65 Eclipse 4.7.1a

    Oxygen.1 von Oktober 2017 unterstützt Java 9 (alte Eclipse-Versionen mit Beta-Plugin besser meiden!) • Eclipse startet mit Java 9 • Java 9 als JRE nutzbar • Code-Completion für module-info für requires, exports, opens … • Launch und Debug kann Module-Path Noch buggy oder fehlt: Fehler bei Automatic Modules, JUnit-Dialoge ohne MP, Unnamed-Package-Compilefehler, keine Optionen für J9-Compiler einstellbar (z.B. --add-exports) Entwicklungstools: Eclipse
  44. Copyright © Accso – Accelerated Solutions GmbH 66 ein Eclipse-

    Projekt == ein Modul Aktuell(?) muss Modellierung der Modul- Beziehungen redundant in Eclipse- Projekten erfolgen
  45. Copyright © Accso – Accelerated Solutions GmbH 67 Strukturen, pom

    unverändert test-compile unterstützt Blackbox- und Whitebox-Tests. test noch mit Classpath. Abhängigkeiten müssen redundant in der pom und in der module-info modelliert werden. Build-Tools: Maven mit Java-9-Support … <dependency> <groupId>de.accso.jigsaw</groupId> <artifactId>moda</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> module modmain { requires moda; }
  46. Copyright © Accso – Accelerated Solutions GmbH 68 Maven test-compile

    baut Blackbox- und Whitebox-Tests wie erwartet. Blackbox: Nur wenn eine module-info.java in src/test/java liegt, erzeugt Maven getrennte Module für Testcode und zu testendes Modul. Sonst automatisch Whitebox: Maven patcht die Testklassen in das Modul wie in unserer Variante 2b. Das surefire-plugin führt die Tests jedoch (noch) auf dem Classpath aus. Maven für Blackbox- und Whitebox-Tests $ javac --patch-module moda=patches/moda ...
  47. Copyright © Accso – Accelerated Solutions GmbH 69 Moditect Generating

    module- info.java descriptors for given artifacts (Maven dependencies or local JAR files) Adding module descriptors to your project's JAR as well as existing JAR files (dependencies) Creating module runtime images https://github.com/moditect/moditect
  48. Copyright © Accso – Accelerated Solutions GmbH 70 Was ist

    „Java9 Ready?“ https://wiki.openjdk.java.net/display/quality/Quality+Outreach
  49. Copyright © Accso – Accelerated Solutions GmbH 72 Zugriff auf

    das Modulsystem über neue API java.lang.… … hat nun Methode getModule() ein Modul ein Layer (gruppiert Module zur Laufzeit) Class Module ModuleLayer
  50. Copyright © Accso – Accelerated Solutions GmbH 73 ModuleDescriptor ModuleDescriptor.Requires

    ModuleDescriptor.Exports ModuleDescriptor.Opens ModuleDescriptor.Provides ModuleReference ModuleFinder Configuration Zugriff auf das Modulsystem über neue API Modulbeschreibung mit Name, Version, … ... mit allen Requires ... mit allen Exports … mit allen Opens … mit allen Provides aber Uses sind leider nur Strings  Laufzeit-Referenz auf ein Modul Ein/alle Module finden („was da ist”) „Was geladen wurde“ java.lang.module.…
  51. Copyright © Accso – Accelerated Solutions GmbH 80 Unser Tool

    „DepVis“ zur Visualisierung von Modul-Graphen Ideen: requires-n-transitive, Filter auf einzelne Beziehungen, Packages, Hashes, nur Module der Configuration, mehr Konfiguration mit Farben & Co … https://github.com/accso/java9-jigsaw-depvis Basiert auf GraphViz http://www.graphviz.org/ mit Java-API https://github.com/kohsuke/graphviz-api Visualisierung und Textausgabe von Modulen auf Module-Path und im System mit Wildcard – Black-&Whitelisting Explicit, Automatic, Open requires (auch 1-transitive, static, mandated), exports-to, opens-to Concealed Packages uses und provides
  52. Copyright © Accso – Accelerated Solutions GmbH 84 Ein Named

    Module darf keine Klassen im Unnamed Package enthalten. Resources sind dagegen im Unnamed Package weiterhin erlaubt. Klassen im Unnamed Package nicht mehr erlaubt src\moda\MyClassInTheUnnamedPackage.java:2: error: unnamed package is not allowed in named modules public class MyClassInTheUnnamedPackage { ^ 1 error Compile- Fehler
  53. Copyright © Accso – Accelerated Solutions GmbH 85 Compile- Fehler

    Laufzeit- Fehler beim Start Ein „Split“ eines Package auf mehrere Module ist nicht erlaubt! Gilt auch, wenn das Package nicht exportiert ist!! Selbst dann, wenn es keine Klassen-Duplikate in den beiden Modulen gibt!!! Split Package: Module müssen disjunkte Packages haben. Ausnahme: Gilt nicht für The Unnamed Module. src\modmainfoo\module-info.java:1: error: module modmainfoo reads package pkgfoo from both modsplitfoo1 and modsplitfoo2 module modmainfoo { ^ 1 error Error occurred during initialization of boot layer java.lang.LayerInstantiationException: Package pkgbar in both module modsplitbar1 and module modsplitbar2 Gilt nur für Module in einer gemeinsamen Configuration (nur auf Module-Path OK).
  54. Copyright © Accso – Accelerated Solutions GmbH 86 jdeps zeigt

    die Verwendung von JDK-internen Klassen: Seit Java 8: Neue offizielle APIs ersetzen unsupportete APIs. Beispiel: sun.misc.BASE64Encoder  java.util.Base64.Encoder Andere APIs werden schrittweise ersetzt, später nicht mehr zugänglich sein. Details siehe JEP 260: http://openjdk.java.net/jeps/260 JDK-interne APIs sind geschützt, nicht mehr zugreifbar! $ jdeps --jdk-internals ./classes pkgmain.Main -> jdk.internal.misc.SharedSecrets JDK internal API (java.base) Warning: JDK internal APIs are unsupported and private to JDK implementation that are subject to be removed or changed incompatibly and could break your application. Please modify your code to eliminate dependence on any JDK internal APIs. For the most recent update on JDK internal API replacements, please check: https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool
  55. Copyright © Accso – Accelerated Solutions GmbH 87 Kill-Switch erlaubt

    einen illegalen Zugriff: permit entspricht einem opens auf alle JDK-internen Packages, aber nur auf die Packages, die es bereits in Java 8 gab! Nur in Java 9 ist permit der Default – nur bis Release 10 (aka 18.3)! Der große Kill-Switch --illegal-access $ java --add-opens=java.base/sun.io=ALL-UNNAMED ... $ java --illegal-access=permit|warn|deny ... Einige prominente Frameworks sind noch nicht auf Java 9 umgestellt. Hauptproblem: Verwendung JDK-interner Klassen per Reflection. Lösung: --add-opens öffnet benötigte Packages für Classpath. • Nachteil: --add-opens muss in allen run-Skripten gesetzt werden! • Bricht zahlreichen existierenden Code!
  56. Copyright © Accso – Accelerated Solutions GmbH 88 Wo finde

    ich diese Java8-Packages? Eine Text-Datei im JDK enthält die Konfiguration aller 1317 Packages von Java 8. Siehe java.base/jdk.internal.module.jdk8_packages.dat Auch online im Sourcen-Repository einsehbar unter http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/65464a307408/src/java.base/ share/classes/jdk/internal/module/jdk8_packages.dat
  57. Copyright © Accso – Accelerated Solutions GmbH 90 Vorschlag: Release

    alle 6 Monate. Wechsel zu „time-based release train“ Nächstes Release bereits im März 2018 als JDK 10 (aka „18.3“) http://openjdk.java.net/projects/jdk/10/ Releases im März & September mit fertigen neuen Features Dazu vier weitere Releases im Jahr mit Security- und Bugfixes Alle 3 Jahre Releases mit LTS (Long-Term-Support), ab 9/2018 https://mreinhold.org/blog/forward-faster #javatrain http://mail.openjdk.java.net/pipermail/discuss/2017- September/thread.html#4281 Warum umsteigen? Neue Release-Policy nach Java 9!
  58. Copyright © Accso – Accelerated Solutions GmbH 92 Module-Path Ein

    „echtes“ Modul: Explicit Module enthält module-info in einem Modular JAR liegt auf dem Module-Path oder auf dem System- Module-Path Open Module ist Spezialfall eines Explicit Modules moda java. base modmain
  59. Copyright © Accso – Accelerated Solutions GmbH 93 Ein JAR

    in ein Modul umwandeln: Automatic Module Module-Path moda java. base JAR auf dem Module-Path modmain junit hat „reads“ auf alle anderen Module „exports“ + „opens“ aller Packages Ein Explicit Module muss ein Automatic Module requiren. Automatischer Name: -  . junit-4.12.jar  junit Named Modules := Explicit Modules + Automatic Modules
  60. Copyright © Accso – Accelerated Solutions GmbH 94 Alle JARs

    auf dem Classpath im „Unnamed Module“ Module-Path modmain moda The Unnamed Module java. base „exports“ aller Packages readable von Automatic Modules nicht ohne weiteres von Explicit Modules hat „reads“ auf alle Module junit a.jar hibernate .jar
  61. Copyright © Accso – Accelerated Solutions GmbH 95 Vorsicht: Der

    Module-Path überdeckt den Classpath! Module-Path moda modmain java. base junit 1 The Unnamed Module a.jar Suchreihenfolge Module-Path The Unnamed Module Vorsicht bei gleichzeitiger Verwendung von Module-Path und Classpath! 2 hibernate .jar 1 2 pkga. A pkga. A Klasse pkga.A wird in moda gefunden! Keine Fehler- meldung, kein Split Package!
  62. Copyright © Accso – Accelerated Solutions GmbH 97 Schritt 0:

    Anwendung (fast) unverändert mit Java 9 benutzen Java-System-Module sind auf dem System-Module-Path Module-Path The Unnamed Module java. base java.xml. bind main.jar a.jar b.jar hibernate.jar Die Anwendung liegt auf dem Classpath (im Unnamed Module).
  63. Copyright © Accso – Accelerated Solutions GmbH 98 Schritt 0:

    Anwendung (fast) unverändert mit Java 9 benutzen Module-Path The Unnamed Module java. base main.jar a.jar b.jar hibernate.jar Hoffentlich keine oder nur minimale Anpassungen notwendig: • Compile- und Runtime-Option --add-modules java.xml.bind java.xml. bind
  64. Copyright © Accso – Accelerated Solutions GmbH 99 Schritt 0:

    Anwendung (fast) unverändert mit Java 9 benutzen Module-Path The Unnamed Module java. base main.jar a.jar b.jar hibernate.jar Vorsicht: Einige inkompatible JDK-Änderungen! Ggf. Updates nötig! Böse Falle: Manche externen Bibliotheken kommen nicht mit dem neuen Java-Versionsnummernkonzept zurecht (z.B. ASM)! Hoffentlich muss man nicht nur deswegen gleich auf die neueste Bibliotheksversion wechseln?! java.xml. bind
  65. Copyright © Accso – Accelerated Solutions GmbH 100 Schritt 1:

    „Normales“ JAR in ein Explicit Module migrieren b.jar hängt von nichts ab. b.jar kann daher einfach in ein Explicit Module migriert werden. Compile- und Runtime-Option --add-modules modb notwendig The Unnamed Module main.jar a.jar hibernate.jar Module-Path java. base b.jar modb java.xml. bind
  66. Copyright © Accso – Accelerated Solutions GmbH 101 Schritt 2:

    JAR in ein Automatic Module migrieren a.jar hängt von hibernate.jar ab. Wird daher erst in ein Automatic Module migriert, damit hibernate.jar readable bleibt. Evtl. Package-Überschneidungen auflösen (Split-Package)! Module-Path java. base modb The Unnamed Module main.jar hibernate.jar a.jar moda java.xml. bind
  67. Copyright © Accso – Accelerated Solutions GmbH 102 Schritt 3:

    Third-Party-Lib in Automatic Module migrieren hibernate wird in ein Automatic Module migriert. Um hibernate in ein Explicit Module zu migrieren, müsste module-info erstellt werden (… das überlassen wir besser dem Maintainer) Module-Path java. base modb moda hiber nate The Unnamed Module main.jar hibernate.jar java.xml. bind
  68. Copyright © Accso – Accelerated Solutions GmbH 103 Schritt 4:

    Automatic Module in Explicit Module migrieren moda kann nun in ein Explicit Module migriert werden, weil hibernate nun ebenfalls im Module-Path liegt. Module-Path java. base modb hiber nate The Unnamed Module main.jar moda moda java.xml. bind
  69. Copyright © Accso – Accelerated Solutions GmbH 104 Schritt 5:

    Den Rest migrieren Module-Path java. base java. sql c junit b main Module-Path java. base modb hiber nate moda main mod main The Unnamed Module main.jar java.xml. bind
  70. Copyright © Accso – Accelerated Solutions GmbH 108 Unser Beispiel:

    Alle Module … zur Laufzeit im Boot Layer Boot Layer
  71. Copyright © Accso – Accelerated Solutions GmbH 109 Zur Laufzeit

    werden Module in sogenannte Layer gruppiert: Jede Modul-“Instanz“ liegt in einem Layer. Layer • haben leider keinen Namen, toString()-Ausgabe zeigt alle Module • haben jeweils eine eigene Configuration. • benötigen mindestens je einen Classloader (pro Layer / pro Module). Es gibt mindestens einen Layer zur Laufzeit („Boot Layer“). Layer bilden eine Hierarchie (aber kein Baum, da mehrere Parents möglich!) Eine Jigsaw-Anwendung besteht zur Laufzeit aus Layern
  72. Copyright © Accso – Accelerated Solutions GmbH 110 Infos zu

    „meinem Layer“ via java.lang.ModuleLayer import java.lang.ModuleLayer; ModuleLayer myLayer = this.getClass().getModule().getLayer(); System.out.println(myLayer.toString()); System.out.println(myLayer.equals(Layer.boot())); List<ModuleLayer> parents = myLayer.parents(); if ( parents.isEmpty() || (parents.size()==1 && parents.contains(Layer.empty()))) { System.out.println("no parents, this is the boot layer"); } else { for (Layer parentLayer: parents) System.out.println(parentLayer.toString()); }
  73. Copyright © Accso – Accelerated Solutions GmbH 111 Beispiel: Variante

    1 – Alle Module im Boot-Layer, siehe ModuleLayer.boot() Boot Layer Zusätzliche Root-Module, per --add-modules übergeben
  74. Copyright © Accso – Accelerated Solutions GmbH 112 Beispiel: Variante

    2 – Layer-Hierarchie erzeugen Pseudo- Parent Empty Layer Foo-Layer Bar-Layer #1 Bar-Layer #2 Boot- Layer Layer-Hierarchie, Boot-Layer ist hier der Parent von 3 Child-Layern
  75. Copyright © Accso – Accelerated Solutions GmbH 113 Layer erzeugen

    mit java.lang.ModuleLayer private ModuleLayer createLayer (final ModuleLayer parentLayer, ClassLoader classLoader, String modName, Set<String> allModuleNames) { // Erzeuge eine Configuration mit den Modul-Namen Configuration cfg = parentLayer.configuration() .resolve(ModuleFinder.of(), moduleFinder, allModuleNames); // Erzeuge einen Child-Layer mit dieser Configuration und CL return parentLayer.defineModulesWithOneLoader (cfg, classLoader); }
  76. Copyright © Accso – Accelerated Solutions GmbH 114 Beispiel: Variante

    2 – Module auf Layer-Hierarchie aufteilen Pseudo- Parent Empty Layer Foo-Layer Bar-Layer #1 Bar-Layer #2 Boot- Layer Aufteilung wäre so nicht möglich, falls modfoo/bar von modmain require‘d würde!
  77. Copyright © Accso – Accelerated Solutions GmbH 115 Beispiel: Variante

    2 – Module aufgeteilt auf Layer-Hierarchie Pseudo- Parent Empty Layer Foo-Layer Bar-Layer #1 Bar-Layer #2 Boot- Layer Layerübergreifende Aufrufe von „oben nach unten“ und umgekehrt via Reflection Kein Split-Package mit mehreren (Geschwister-) Layern Statische Aufrufe möglich von modfoo und modbar nach modcommon Module in verschiedenen Versionen möglich
  78. Copyright © Accso – Accelerated Solutions GmbH 116 Layer-übergreifende Reflection-Calls

    private void call(ModuleLayer layer, String modName, String clazzName, String methodName) throws Exception { Class<?> clazz = layer.findLoader(modName).loadClass(clazzName); Constructor<?> con = clazz.getDeclaredConstructor(); con.setAccessible(true); Object o = con.newInstance(); Method m = o.getClass().getMethod(methodName); m.setAccessible(true); m.invoke(o); } Layerübergreifende Aufrufe mit Layer und Module-Name möglich
  79. Copyright © Accso – Accelerated Solutions GmbH 118 https://github.com/accso/java9-jigsaw-examples/ Läuft

    mit Java Release-Build b181 und 9.0.1 Bash-Skripte für Compile, Run, Test (in Windows z.B. mit Babun nutzbar) Projekte für Eclipse 4.7.1a Unsere 32 Beispiele zeigen alles Wissenswerte zu Jigsaw zu Requires, Exports, Exports-To, Requires-Static, Requires-Transitive, Blackbox-Test, Whitebox-Test, Uses, Provides, Maven-Integration, Opens, Open Module, Manifest-Optionen, versteckte Main-Klasse, Automatic Modules, Reflection, Resolved Modules (Configuration), Naming von Modulen, Unnamed Module (Classpath), Layer, Javadoc, Annotations, jlink etc. pp. usw. usf. Unsere Jigsaw-Beispiele stehen auf Github
  80. Copyright © Accso – Accelerated Solutions GmbH 123 Drastische Semantikänderung:

    public != accessible Selbst bei Reflection. Abhängigkeitsmodell wirkt sehr statisch. • Für die Java-Plattform passt das, da hat man alle Klassen zur Compile-Zeit. Anwendungen sind viel dynamischer. • Requires: Warum fehlen Scopes wie „Test“ und „Runtime“ (vgl. Maven)? Zugriffsschutz ist sehr restriktiv. • Opt-in oder Opt-out? • Exports: Keine Unterstützung von Package-Wildcards! • Erster Accessibility-Level ist nun das „Package“. (Warum eigentlich?) Gleiche Konzepte nicht immer konsistent benamt (requires  reads) Kritik …
  81. Copyright © Accso – Accelerated Solutions GmbH 124 Kritik …

    Ein Modul hat keine (echten) Versionen - nur informell Kein Alias für ein Modul möglich außer --patch-module Module sind nicht gruppierbar. Keine Hierarchie (vgl. Maven parent.pom) Gut: Aggregator-Module über requires transitive Redundanzen zwischen Tools und module-infos module-info wird zu .class-File kompiliert. Ist aber doch gar keine Klasse. Warum nicht MANIFEST.MF? Oder wenigstens Human-Readable-Format? Warum kann man bei --add… keine module-info übergeben / patchen?
  82. Copyright © Accso – Accelerated Solutions GmbH 125 Aus der

    Mailingliste zu „warum module-info als .class?“
  83. Copyright © Accso – Accelerated Solutions GmbH 126 Der richtige

    Schritt zur echter Komponentenorientierung! Jigsaw und Java 9 sind (schon lange) stabil. Allerdings sehr viel Dynamik: Implementierungen (und auch Konzepte, gerade zu Reflection) wurden bis zuletzt geändert. Kill-Switch war Antwort auf die JCP-Ablehnung im April 2017. Migration ist gut machbar, aber wird mühsam! • Modul-Kategorien: „Wo kommt was her?“ ist nicht trivial! • MP & CP: Bekommen wir das jemals richtig aussortiert? • Observable != Configuration  ClassNotFoundException • Letzte Rettung: --add-modules ALL-MODULE-PATH … und Lob!
  84. Copyright © Accso – Accelerated Solutions GmbH 127 Drastische Semantikänderung:

    public != accessible Erster Accessibility-Level ist nun das „Package“. (Warum eigentlich?) Zugriffsschutz ist sehr restriktiv. Opt-in oder Opt-out? Leider keine Wildcards bei Exports-Package! Ein Modul hat keine (echten) Versionen - nur informell module-info wird zu .class-File kompiliert. Ist aber doch gar keine Klasse. Warum nicht MANIFEST.MF? Oder wenigstens Human-Readable-Format? Abhängigkeitsmodell ist sehr statisch über Namen. Kein Alias für ein Modul möglich (außer --patch-module) Module sind nicht gruppierbar. Keine Hierarchie möglich (vgl. parent.pom) Warum keine Scopes wie „Test“ und „Runtime“ (vgl. Maven)? Kritik …
  85. Copyright © Accso – Accelerated Solutions GmbH 128 Der richtige

    Schritt zur echter Komponentenorientierung! Jigsaw und Java 9 sind sehr stabil. Allerdings sehr viel Dynamik: Implementierungen (und auch Konzepte, gerade zu Reflection) wurden bis zuletzt geändert. Kill-Switch als Antwort auf JCP-Ablehnung im April 2017. Aggregator-Module über requires transitive Migration ist gut machbar, aber wird mühsam! • Modul-Kategorien: „wo kommt was her?“ ist nicht trivial! • MP & CP: Bekommen wir das jemals richtig aussortiert? … und Lob!
  86. Copyright © Accso – Accelerated Solutions GmbH 132 Weitere JPMS-nahe

    Themen in Java 9 JavaDoc, Annotations funktioniert erwartungskonform Deprecation für Module ClassLoader hat sich im Grundprinzip nicht geändert -Xbootclasspath fällt weg Upgradeable Modules i.W. Ersatz für Extension-Mechanismus jlink für Linking optimierter Runtime-Images Multi-Release-JAR-Files mit Java-Release- JEP 238 spezifischen Inhalten JMOD-Format und -Dateien i.W. JARs mit Native-Code usw.
  87. Copyright © Accso – Accelerated Solutions GmbH 133 Andere Neuheiten

    in Java 9 – Project Coin JEP 213 Interfaces Private Helper-Methoden möglich Try-With-Resources für Effectively Final Auto-Closeables Anonymous Diamond Operator @SafeVarargs für Generics & Varargs Underscore _ ist kein erlaubter Identifier mehr siehe auch https://tiny.cc/java-9/ X<?> x = new X<>(){}; // X<> ist neu ab Java9 class X<T> {} @SafeVarargs private int getLen(List<String>...list) { List<String>[] l = list; return l.length; }
  88. Copyright © Accso – Accelerated Solutions GmbH 134 Andere Neuheiten

    in Java 9 – JDK, Tools Neuer Versionsstring $MAJOR.$MINOR.$SECURITY.$PATCH JEP 223 GNU-Command-Line-Options für javac, java, … JEP 293 jshell REPL JEP 222 jhat, hprof gibt es nicht mehr JEP 240, 241 UTF-8 Property Files JEP 226 siehe auch https://tiny.cc/java-9/ $ java --version java 9 Java(TM) SE Runtime Environment (build 9+181) Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode) $ java -Xinternalversion Java HotSpot(TM) 64-Bit Server VM (9+181) for windows-amd64 JRE (9+181), built on Aug 2 2017 21:30:51 by "javare" with MS VC++ 12.0 (VS2013)
  89. Copyright © Accso – Accelerated Solutions GmbH 135 Andere Neuheiten

    in Java 9 – Deprecation JEP 277 Deprecation @Deprecated(since=9, forRemoval=true) Zeigt keine Warning Statt @SuppressWarnings("deprecation") bei „nur-Import“ mehr an. Warning kam früher noch für import, ab Java9 weg! siehe auch https://tiny.cc/java-9/ import java.io.LineNumberInputStream; @Deprecated public class Test { LineNumberInputStream stream; }
  90. Copyright © Accso – Accelerated Solutions GmbH 136 Andere Neuheiten

    in Java 9 - APIs Deprecated APIs Applet-API ist deprecated. JEP 289 Java-Plugin ist aber (noch) da. Neue APIs Stack-Walking-API JEP 259 Process-API JEP 102 Streams, Optional, Factories JEP 269 Concurrency, Reactive Streams JEP 266 Deserialization Filter JEP 290 Multi-Resolution Images JEP 251 HTTP/2 JEP 110 siehe auch https://tiny.cc/java-9/
  91. Copyright © Accso – Accelerated Solutions GmbH 137 Andere Neuheiten

    in Java 9 – Performance JEP 254 Compact Strings ist per Default aktiviert! Typische Anwendungen nutzen ca. 20-30% des Heaps für Strings. Falls kein UTF-8 benötigt (mit je 2 Bytes pro Zeichen), sind 10-15% verschwendet! java.lang.String nutzt nun byte[] statt char[] je nach Encoding siehe auch https://tiny.cc/java-9/ // Java 8 public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; // Java 9 public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. … @Stable private final byte[] value;
  92. Copyright © Accso – Accelerated Solutions GmbH 139 Homepage Project

    Jigsaw OpenJDK: JDK 9 Oracle: JDK 9 Documentation Jigsaw-Issues Specification (2015) State of the Module System (2016) Quickstart Guide JSR376 JEPs 200 „The modular JDK“ 220 „Modular Runtime Images“ 260 „Encapsulate Most Internal APIs“ Mailinglisten jigsaw-dev, jdk9-dev, jpms-spec-comments, jpms-spec-experts, jpms-spec-observers 261 „Module System“ 275 „Modular Java App. Packaging“ 282 „jlink: The Java Linker“ http://mail.openjdk.java.net/mailman/listinfo http://openjdk.java.net/projects/jigsaw/ http://openjdk.java.net/projects/jdk9/ https://docs.oracle.com/javase/9/ http://openjdk.java.net/projects/jigsaw/spec/issues/ http://openjdk.java.net/projects/jigsaw/spec/reqs/ http://openjdk.java.net/projects/jigsaw/spec/sotms/ http://openjdk.java.net/projects/jigsaw/quick-start https://www.jcp.org/en/jsr/detail?id=376 http://openjdk.java.net/jeps/<NR> Zum Nachlesen
  93. Copyright © Accso – Accelerated Solutions GmbH 140 http://accso.de/java/ JavaSPEKTRUM-

    Sonderdruck zu Java 9 / Jigsaw oder heute hier zum Mitnehmen
  94. Copyright © Accso – Accelerated Solutions GmbH 141 141 141

    Accso – Accelerated Solutions GmbH T | +49 6151 13029-0 E | [email protected] @ | www.accso.de Berliner Allee 58 | 64295 Darmstadt Moltkestraße 131a | 50674 Köln Balanstraße 55 | 81541 München https://de.slideshare.net/lemmi @accso @lemmi111171 @krschaal https://github.com/accso/java9-jigsaw-examples/ https://github.com/accso/java9-jigsaw-depvis/