Post on 21-Jan-2017
Copyright © Accso – Accelerated Solutions GmbH 1
DAS NEUE MODULSYSTEM JIGSAWIN JAVA 9
31. AUGUST 2016 | MARTIN LEHMANN, DR. KRISTINE SCHAAL | HERBSTCAMPUS 2016, NÜRNBERG
EIN GEDULDSSPIEL! DAS 1000-MODULE-PUZZLE FÜR ENTWICKLER
Copyright © Accso – Accelerated Solutions GmbH 2
Historie
Datum von? Änderung Bemerkung
31.08.2016 Martin Lehmann, Kristine Schaal finale Version für Herbstcampus 2016
01.09.2016 Martin Lehmann Minimalkorrekturen bei den neuen --add... Optionen (die –Xadd… ersetzten): Diese werden ohne : geschrieben, stattdessen Blank nach der Option.
Optionen für javac und java ändern sich, werden GNU-Style, siehe JEP293
Copyright © Accso – Accelerated Solutions GmbH 3
Mit Java 9 kommt 2017 das lange angekündigte Modulsystem Jigsaw - eine grundlegende Strukturänderung von Java-Plattform und -Sprache -, mit deren Auswirkungen man sich möglichst früh beschäftigen sollte. Wir erläutern technische Grundlagen, zeigen anhand von Code-Beispielen, wie das Modulsystem aussieht und welche Designentscheidungen getroffen wurden. Wir zeigen Motive und Ziele für die Einführung eines Modulsystems. Weiterhin gehen wir auf Auswirkungen von Modulen zur Compile- und Laufzeit ein, z.B. auf häufig in Frameworks anzutreffende generische Ansätze wie Reflection oder Callbacks. Abschließend behandeln wir fortgeschrittene Themen wie Migrationspfade, Architektur und Komponentenschnitt.
Skills Java-Grundlagen (Sprache und Architektur), idealerweise Verständnis von Maven oder Ivy
LernzieleZuhörer erhalten eine Einführung in das neue Jigsaw-Modulsystem, verstehen die Grundlagen und die Auswirkungen auf Architektur und Komponentenschnitt. Außerdem lernen sie Migrationspfade nach Java 9 kennen.
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.
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.
Abstracthttp://www.herbstcampus.de/veranstaltung-5217-das-neue-modulsystem-jigsaw-in-java-9.html?id=5217
2017/03/23 Java 9 General Availabilityhttp://openjdk.java.net/projects/jdk9/
Copyright © Accso – Accelerated Solutions GmbH 6
JSR 277 (2005-2016) „Java Module System“
JSR 294 (2006-2016) „Improved Modularity Support”
JSR 291 (2006-2007) „Dynamic Component Support“
JSR 376 (2014-2017) „Java Platform Module System“
Project Jigsaw für Java 9 geplant für März 2017
Copyright © Accso – Accelerated Solutions GmbH 7
Ziele von Modularisierung und Jigsaw
Reliable ConfigurationAblösung des Classpath (fehleranfällig, wenn Klassen mehrfach enthalten sind – Reihenfolge). Neu: explizite Definition von Abhängigkeiten.
Strong EncapsulationEine Komponente kann ihr öffentliches API definieren und verhindern, dass auf Implementierungsgeheimnisse zugegriffen wird.
Scalable Java SE PlatformDie Java-Plattform selber wird modularisiert. Damit kann man individuell angepasste und „schlanke“ Plattformen bauen.
Copyright © Accso – Accelerated Solutions GmbH 8
Modules mit Dependencies, Resolution, Encapsulation, Non-Interference: In allen Phasen (Compile, Laufzeit). Exports müssen von außen überschreibbar sein.
Resource Encapsulation
Services: Binding, Selective Binding
Java Platform Modularization
Interoperabilität mit anderen Modulsystemen (OSGi explizit genannt)
Refactoring: Module aufspaltbar / zusammenlegbar, ohne Auswirkungen auf Clients
Whitebox-Tests
Schrittweise Migration, Weiterbenutzung von existierenden Tools wie Maven
Linking („optimierte Plattform bauen“)
Keine Verschlechterung der Performance
Non-Requirements: Versionierung – nur als Versionsstring in Module ?!
Die wichtigsten Requirements aus der Spec-Dokumentation
Copyright © Accso – Accelerated Solutions GmbH 10
Modul := Menge von Java-Packages & Resources.
Wird in ein „Modular JAR“ kompiliert. Dieses liegt im neuen Module-Path.
Modul-Namen müssen eindeutig sein (. und _ sind im Namen erlaubt, - nicht)
• „read“-Abhängigkeitsbeziehungen zu einem oder mehrerenanderen Modulen
• „exports“: Welche Packages des Moduls werden exportiert?(Default: nichts!)
moda
Ein Modul wird ein „First-Class-Citizen“ in Java
modb
read
exports
pkga
pkgb
pkgbinternal
Copyright © Accso – Accelerated Solutions GmbH 11
de.my.package
...
Foo Bar
XYZBaz
protected
private<package>
public
Java 1.0 bis 8: Sichtbarkeitsmodifier von Klassen, Attributen, Methoden
Copyright © Accso – Accelerated Solutions GmbH 12
Java 1.0 bis 8: Sichtbarkeitsmodifier von Klassen, Attributen, Methoden
Copyright © Accso – Accelerated Solutions GmbH 13
Java 9: Diese Sichtbarkeitsmodifier ändern sich nicht.
Copyright © Accso – Accelerated Solutions GmbH 14
de.my.mod
Neu in Java 9: Modul-Definition mit exportierten Packages
exports
Copyright © Accso – Accelerated Solutions GmbH 15
Neu in Java 9: Readability und Accessibility
read moda
pkga
Check zu Compile-Zeit und zur Laufzeit vonReadability: „ich benötige dieses Module, will darauf zugreifen“
Accessibility: „auf was genau dürfen andere zugreifen?“ (unabhg. von Classloadern!)
1. Check: Readable (über requires)? Accessible (über exports)?
2. Check wie bisher der Sichtbarkeitsmodifier public,protected,<package>,private
de.my.package.ximpl
de.my.package.internal
de.my.package
exports
de.my.mod
Copyright © Accso – Accelerated Solutions GmbH 16
Beispiel: Vier Module moda, modb,modc, modmain und ihr Sourcenbaum
moda/module-info.javapkga1/
A1.javapkga2/
A2.javapkga3/
A3.javapkgainternal/
InternalA.javamodb/
module-info.javapkgb/
B.javamodc/
module-info.javapkgc/
C.javamodmain/
module-info.javapkgmain/
Main.java
Copyright © Accso – Accelerated Solutions GmbH 17
moda/module-info.javapkga1/
A1.javapkga2/
A2.javapkga3/
A3.javapkgainternal/
InternalA.javamodb/
module-info.javapkgb/
B.javamodc/
module-info.javapkgc/
C.javamodmain/
module-info.javapkgmain/
Main.java
Modul-Definition eines Modules liegt in Datei module-info.java
im obersten Module-Sourcenverzeichnis.
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
Copyright © Accso – Accelerated Solutions GmbH 19
module moda {// Read-Abhängigkeiten von moda zu modb und modc// (Compiler meckert fehlende Module an!)
requires modb;requires public modc; // transitiv!
// Exports von Packages von moda// (Compiler meckert fehlende Packages an!)
exports pkga1;exports pkga2 to modmain; // nur an modmain
exports dynamic pkga3; // nur zur Laufzeit// siehe Reflection
// dazu noch: uses und provides (siehe hinten)}
moda/module-info.javapkga1/
A1.javapkga2/
A2.javapkga3/
A3.javapkgainternal/
InternalA.javamodb/
module-info.javapkgb/
B.javamodc/
module-info.javapkgc/
C.javamodmain/
module-info.javapkgmain/
Main.java
module-info.java
modmain
moda/module-info.java
Copyright © Accso – Accelerated Solutions GmbH 20
Alle Abhängigkeiten der vier Module moda, modb, modc, modmain
moda/module-info.javapkga1/
A1.javapkga2/
A2.javapkga3/
A3.javapkgainternal/
InternalA.javamodb/
module-info.javapkgb/
B.javamodc/
module-info.javapkgc/
C.javamodmain/
module-info.javapkgmain/
Main.java
Copyright © Accso – Accelerated Solutions GmbH 21
requires public ist transitiv
module moda {requires modb;requires public modc;
...
Copyright © Accso – Accelerated Solutions GmbH 22
package pkga1;
import pkgb.B;import pkgc.C;
public class A1 {public String doIt() {
return "from A1, " + new B().doIt();}
public C getMyC() {return new C();
}}
moda/pkga1.A1.javamoda/
module-info.javapkga1/
A1.javapkga2/
A2.javapkga3/
A3.javapkgainternal/
InternalA.javamodb/
module-info.javapkgb/
B.javamodc/
module-info.javapkgc/
C.javamodmain/
module-info.javapkgmain/
Main.java
A1.javamodmain
Copyright © Accso – Accelerated Solutions GmbH 23
modmain/pkgmain.Main.javamoda/
module-info.javapkga1/
A1.javapkga2/
A2.javapkga3/
A3.javapkgainternal/
InternalA.javamodb/
module-info.javapkgb/
B.javamodc/
module-info.javapkgc/
C.javamodmain/
module-info.javapkgmain/
Main.javaMain.java
modmainpublic class Main {public static void main(String[] args) throws Exception {
// access to pkga1 (exported from moda)pkga1.A1 mya1 = new pkga1.A1();System.out.println("A1: " + mya1.doIt());
Object myc1 = mya1.getMyC();System.out.println("from A1: getMyC()=" + myc1);
pkgc.C myc2 = mya1.getMyC();System.out.println("from A1: getMyC()=" + myc2);
// access to pkga2 (exported from moda only to modmain)pkga2.A2 mya2 = new pkga2.A2();System.out.println("A2: " + mya2.doIt());
...
Copyright © Accso – Accelerated Solutions GmbH 24
public class Main {public static void main(String[] args) throws Exception {...// access to pkga3 (exported dynamic from moda)// does not compile, pkga3 only via reflection// pkga3.A3 mya3 = new A3();
Class<?> myA3Class = Class.forName("pkga3.A3");Constructor<?> con = myA3Class.getDeclaredConstructor();con.setAccessible(true);Object myA3 = con.newInstance();Method m = myA3.getClass().getMethod("doIt");m.setAccessible(true);System.out.println("A3: " + m.invoke(myA3));
// does not compile, pkgainternal not exported// pkgainternal.InternalA myinternalA = // new pkgainternal.InternalA();}
modmain/pkgmain.Main.javamoda/
module-info.javapkga1/
A1.javapkga2/
A2.javapkga3/
A3.javapkgainternal/
InternalA.javamodb/
module-info.javapkgb/
B.javamodc/
module-info.javapkgc/
C.javamodmain/
module-info.javapkgmain/
Main.java
modmain
Main.java
Copyright © Accso – Accelerated Solutions GmbH 25
Compile
Run
Compile / Run-Skripte (Bash)
$JAVA_HOME/bin/java --module-path mlib -m modmain/pkgmain.Main
$JAVA_HOME/bin/javac -d mods --module-path mlib-modulesourcepath src $(find src -name "*.java")
Copyright © Accso – Accelerated Solutions GmbH 26
Auf Github: https://github.com/accso/java9-jigsaw-examples/
Java mit Jigsaw Build 9-ea+127-jigsaw-nightly-h5308-20160721
Eclipse 4.6 Neon plus Java9-Support (BETA)
• Konvention: 1 Eclipse-Projekt == 1 Module
• Module-Namen: mod*, Package-Namen: pkg* (interne *internal)
• Module-Abhängigkeiten über Projekt-Abhängigkeiten in Eclipse nachmodelliert
• Launch-Files starten die JAR-Files im Module-Path
• Jedes Beispiel in einem eigenen Workspace *)
Compile- und Run-Skripte für die Bash (auch für Windows, z.B. mit Babun)
Unsere Beispiele
*) Ein Workspace kann nicht 2 Projekte gleichen Namens enthalten.
Copyright © Accso – Accelerated Solutions GmbH 28
Was ist mit Reflection? … und mit Serialisierung, Dependency-Injection, Bytecode-Enhancement, ...?
Zur Erinnerung
1. Check: Readable (über requires)? Accessible (über exports)?
2. Check wie bisher von public,protected,<package>,private
Gilt alles auch bei Reflection!
Convenience bei Reflection: read-Beziehung ist immer vorhanden.
Aber Accessibility-Checks greifen auch „scharf“ bei Reflection: Klassen von nicht exportierten Packages sind nicht zugreifbar.
• Gilt für newInstance, getField, getMethod
• Gilt auch für setAccessible(true)
„exports dynamic“ erlaubt Zugriff nur zur Laufzeit, nicht zur Compile-Zeit
Copyright © Accso – Accelerated Solutions GmbH 29
Letztlich geht‘s immer um Typen-Sichtbarkeit. Auch bei Ableitung.
Funktioniert:
• Oberklasse Data ist sichtbar nach außen,weil Package pkga exportiert.
• Ihre Methoden sind von außerhalb aufrufbar.
• Unterklasse InternalData ist nicht sichtbar nach außen.
• Ihre Methoden sind von außerhalb nicht aufrufbar.
exports
pkgainternal
pkgaData
moda
Internal
Data
Copyright © Accso – Accelerated Solutions GmbH 30
Funktioniert auch umgekehrt:
• Oberklasse ist nicht sichtbar nach außen
• Unterklasse ist sichtbar nach außen
pkgaData
moda
exports
pkgainternal
Internal
Data
Letztlich geht‘s immer um Typen-Sichtbarkeit. Auch bei Ableitung.
Copyright © Accso – Accelerated Solutions GmbH 31
pkgainternal
pkga
moda
Fact
ory
Internal
Data
Data
exports
Funktioniert: Factory gibt Instanzen der Unterklasse InternalData zurück.
Instanzen behalten natürlich ihren Typ.
Es werden Methoden der Unterklasse aufgerufen, z.B. InternalData.toString()
public class Factory {public Data createData() {
return new Data(); }
public Data createInternalData1() {return new InternalData();
}…
Letztlich geht‘s immer um Typen-Sichtbarkeit. Auch bei Ableitung.
Copyright © Accso – Accelerated Solutions GmbH 32
Gilt auch bei Ableitung
Was passiert, wenn eine Methodensignatur eine nicht exportierte Klasse zurückgibt
pkgainternal
pkga
moda
Fact
ory
public class Factory {public Data createData() {
return new Data(); }
public Data createInternalData1() {return new InternalData();
}
// return type wird nicht exportiert!public InternalData createInternalData2() {
return new InternalData();}
}
Factory kompiliert.
Code in anderem Module kompiliert nicht bei Aufruf:
Internal
Data
Data
exports
Factory.createInternalData2()
Letztlich geht‘s immer um Typen-Sichtbarkeit. Auch bei Ableitung.
Copyright © Accso – Accelerated Solutions GmbH 33
Interne Exceptions (deren Package nicht exportiert ist)MyInternalExceptionMyInternalRuntimeException
können nach außerhalb des Modules geworfen werden.
Typ bleibt auch hier erhalten.
Alles funktioniert „ganz normal“, nur eben kein catch auf den internen Exception-Typ.
catch auf Oberklassen wie Exception, RuntimeExceptionproblemlos möglich.
Letztlich geht‘s immer um Typen-Sichtbarkeit.Gilt auch bei Exception-Handling.
Copyright © Accso – Accelerated Solutions GmbH 34
Eine Implementierung eines Interfaces muss nicht exportiert sein, um benutzt werden zu können.
Beispiel Callback-Interface:
exports
pkgsst
ICall
back
Call
eepkg
internalCall
back
Impl
read
Letztlich geht‘s immer um Typen-Sichtbarkeit.Gilt auch bei Implementierung eines Interfaces.
Copyright © Accso – Accelerated Solutions GmbH 36
Beispiel
Schnittstelle java.sql.Driver Implementierungin Module java.sql in JDBC-Driver
keine feste Bindung über Module-Namen wie bei Requires
Interfaces und Implementierung mit Uses/Provides in der module-info
module java.sql {…
// Definiert Schnittstelle uses java.sql.Driver;
// ... und exportiert sie auchexports java.sql;
}
module com.mysql.jdbc {requires java.sql;
…// Implementiert Schnittstelle
provides java.sql.Driverwith com.mysql.jdbc.Driver;
}
Copyright © Accso – Accelerated Solutions GmbH 37
Zugriff auf Module-interne Resources möglich mit
Funktioniert weiterhin:
Leider keine Resource-Encapsulation. (Ursprüngliches Requirement dazu wird wohl gekippt.) Ein Module kann auf Resources eines anderen Modules zugreifen, sofern dieses readable ist.
Resource-Handling in Modules
this.class.getModule().getResourceAsStream("myapp.properties")
this.getClass().getResource ("myapp.properties")
ClassLoader.getPlatformClassLoader().getResource("myapp.properties")
that.class.getModule().getResourceAsStream("that.properties")
Copyright © Accso – Accelerated Solutions GmbH 38
Compile-Fehler
Laufzeit-Fehlerbeim Start
Kein „Split“ eines Packages auf zwei Modules erlaubt!
Gilt auch, wenn das Package nicht exportiert ist.
Selbst dann, wenn es keine Klassen-Duplikate in den beiden Modules gibt.
Split Package: Modules 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 modsplitfoo2module modmainfoo {^1 error
Error occurred during initialization of VMjava.lang.reflect.LayerInstantiationException: Package pkgbar in both module modsplitbar1 and module modsplitbar2at java.lang.reflect.Layer.fail(java.base@9-ea/Layer.java:449)at java.lang.reflect.Layer.checkBootModulesForDuplicatePkgs(java.base@9-ea/Layer.java:407at java.lang.reflect.Layer.defineModules(java.base@9-ea/Layer.java:357)at jdk.internal.module.ModuleBootstrap.boot(java.base@9-ea/ModuleBootstrap.java:298at java.lang.System.initPhase2(java.base@9-ea/System.java:1925)
Gilt nur für Module in einer gemeinsamen Configuration – nur auf Module-Path OK.
Copyright © Accso – Accelerated Solutions GmbH 39
Wie kann man dasstatische Modell
ändern/erweitern?
Copyright © Accso – Accelerated Solutions GmbH 40
„Du kommst hier nicht rein!“
ist nicht exportiert, nicht zugreifbar (sog. „concealed package“)!
moda/module-info.javapkga1/
A1.javapkga2/
A2.javapkga3/
A3.javapkgainternal/
AHelperImpl.javamodb/
module-info.javapkgb/
B.javamodc/
module-info.javapkgc/
C.javamodmain/
module-info.javapkgmain/
Main.java
moda/module-info.javapkga1/
A1.javapkga2/
A2.javapkga3/
A3.javapkgainternal/
InternalA.javamodb/
module-info.javapkgb/
B.javamodc/
module-info.javapkgc/
C.javamodmain/
module-info.javapkgmain/
Main.java
pkgainternal/InternalA.java
pkgainternal
Doch!
Unschön
JAR-File mit neuem module-info.classpatchen ist i.d.R. keine Alternative(geht z.B. nicht bei Checksummen)
Abhilfe
Kommandozeilenoption --add-exportsgibt Export zusätzlicher Packages an
Copyright © Accso – Accelerated Solutions GmbH 41
… wenn Exports und Reads der module-info nicht reichen
weiteres Package exportieren
Neue Read-Beziehung von->nach
Kommandozeile javac, java
weiteres (Root-)Module laden
Module mit Klassen patchen
Byte-Code-Manipulation kann auch dynamisch Modules umschreiben
Reflection
--add-exports
java.lang.reflect.Module.addExports()
--add-reads
java.lang.reflect.Module.addReads()
--add-modules
„Nimm-Alles“ ALL-MODULE-PATH
--patch-module
Kein Patch von module-info !
Kommandozeile javac, java
Copyright © Accso – Accelerated Solutions GmbH 43
Separates Module modtest.blackbox testet äußere Schnittstelle von modfib. Braucht also keinen Zugriff auf interne Klassen.
Blackbox-Test eines Modules modfib
modfibmodtest.blackbox
read
exports
pkg blacktest
pkgfibinternal
pkgfib
java --module-path mlib\;amlib--add-modules hamcrest.core,modtest.blackbox-m junit/org.junit.runner.JUnitCore pkgblacktest.BlackBoxTest
Copyright © Accso – Accelerated Solutions GmbH 44
Whitebox-Test eines Modules modfib : 4 Varianten
Ein Whitebox-Test benötigt zum Test interne Klassen von modfib. Das Package pkgfib.internal ist aber nicht exportiert.
modfibexports
pkgfibinternal
pkgfib
Copyright © Accso – Accelerated Solutions GmbH 45
1. Separates Module modtest.whiteboxWie erhält es Zugriff auf die nicht-exportierten Klassen von modfib?
Whitebox-Test eines Modules modfib : Varianten 1a, b
Statische Abhängigkeit zu Testcode
Etwas besser. Aber: Pflege der Skripte?!
module modfib {exports pkgfib; exports pkgfibinternal to modtest.whitebox;
}
a) Mit „exports to“ der zu testenden Packages an modtest.whitebox
javac --add-exports modfib/pkgfib.internal=modtest.whitebox
java --add-exports modfib/pkgfib.internal=modtest.whitebox
b) Dynamischer Export der zu testenden Packages mit --add-exports
Copyright © Accso – Accelerated Solutions GmbH 46
2. modfib enthält auch die Testklassen.Aber wo verwaltet man diese?
Whitebox-Test eines Modules modfib : Varianten 2a, 2b
Testcode wird ebenfalls paketiert und deployed
a) Testklassen direkt bei modfib ablegen.Testklassen können so alle zu testenden Klassen aus modfib sehen.
b) Testklassen getrennt ablegen.Zu Compile-Zeit und zur Test-Laufzeit dem Module modfib hinzufügen („Patchen“)
Copyright © Accso – Accelerated Solutions GmbH 47
Whitebox-Test Variante 2b: modfib mit Testklassen patchen
Testklassen erst beim Compile dem Module modfib hinzufügen
modfib
pkgfibinternal
pkgfib pkgfib
…Test
javac -Xmodule:modfib --add-reads modfib=junit-d patches/modfib ... src/modtest.whitebox/pkgfib/WhiteBoxTest.java
Copyright © Accso – Accelerated Solutions GmbH 48
modfib
pkgfibinternal
pkgfib pkgfib
…Test
Testklassen erst beim Test-Start dem Module modfib hinzufügen
Whitebox-Test Variante 2b: modfib mit Testklassen patchen
java --patch-module modfib=patches/modfib--add-reads modfib=junit...-m junit/org.junit.runner.JUnitCore pkgfib.WhiteBoxTest
Copyright © Accso – Accelerated Solutions GmbH 50
Observable Modules
System-Module-Path
Observable Modules: „Was da ist“
java.base
Module-Path
modmain
Alle Module auf dem Module-Path, sowie die System-Module bilden das „Universum“ der Observable Modules.
Copyright © Accso – Accelerated Solutions GmbH 51
Die Configuration ist die transitive Hülle aller „reads“-Abhängigkeiten aller Root-Module der Observable Modules.
Default-Root-Module hier: modmain
Observable Modules
System-Module-Path
Configuration: „Was wirklich geladen wird“
Module-Path
modmain
java.base
java --module-path mlib -m modmain/pkgmain.Main
modmain
java.base
Copyright © Accso – Accelerated Solutions GmbH 52
Weitere Module kann man einer Configuration als Root-Module mit --add-moduleshinzufügen:
Observable Modules
System-Module-Path
Configuration: „Was wirklich geladen wird“ plus „addMods“
Module-Path
modmain
java.base
modmain
java.base
java --module-path mlib --add-modules mlib/modx.jar -m modmain/pkgmain.Main
modxmodx
Copyright © Accso – Accelerated Solutions GmbH 54
Module-Path
Ein „echtes“ Module: Explicit Module
Explicit Module
in einem JAR
liegt auf dem Module-Path
enthält module-infomodb
java.base
modmain
Copyright © Accso – Accelerated Solutions GmbH 55
Ein JAR in ein Module umwandeln: Automatic Module
Module-Path
modb
java.base
Automatic Module
JAR auf den Module-Path legenmodmain
junit
Automatisch: „reads“ auf alle Module, „exports“ aller Packages
Ein Explicit Module muss ein Automatic Module requiren.
Automatischer Name: - . junit-4.12.jar junit
Named Modules := Explicit Modules + Automatic Modules
Copyright © Accso – Accelerated Solutions GmbH 56
Der alte Classpath: The Unnamed Module
The Unnamed Module
Alle JARs auf dem Classpathsind ein einziges Module
Module-Path
modmain
modb
The Unnamed Module
java.base
Exports aller Packages
Readable durch alle(!) Automatic Modules, aber nicht durch Explicit Modules
„reads“ auf alle Modules
junit
b.jar
hibernate.jar
Copyright © Accso – Accelerated Solutions GmbH 57
Wie Module-Path und The Unnamed Module interagieren
Module-Path
modb
modmain
java.base
junit
1 The Unnamed Module
b.jar
Suchreihenfolge
Module-Path
The Unnamed Module
Vorsicht bei gleichzeitiger Verwendung von Module-Path und The Unnamed Module!
2
hibernate.jar
1
2
pkgb.B
pkgb.B
Klasse pkgb.B wird in modbgefunden! Keine Fehler-meldung wie bei Split Package!
Copyright © Accso – Accelerated Solutions GmbH 59
Schritt 0: Anwendung unverändert mit Java 9 benutzen
Die Java-Plattform-Module auf dem System-Module-Path
Module-Path The Unnamed Module
java.base
java.sql
main.jar
b.jar c.jar
hibernate.jar
Die Anwendung liegt auf dem Classpath (im Unnamed Module).
Keine Anpassungen notwendig, jedoch ohne Named Modules.
ABER: Wenige inkompatible Änderungen in Java 9, z.B. kein Boot-Classpath
Copyright © Accso – Accelerated Solutions GmbH 60
Schritt 1: „Unabhängiges“ JAR in Named Module migrieren
c.jar hängt von nichts ab.
c kann einfach in ein Named Module migriert werden.
Compile- und Runtime-Option --add-modules notwendig!
The Unnamed Module
main.jar
b.jar
hibernate.jar
Module-Path
java.base
java.sql
c.jar
c
Copyright © Accso – Accelerated Solutions GmbH 61
Schritt 2: JAR in Automatic Module migrieren
b.jar hängt von hibernate.jar ab. Wird als Automatic Module migriert, damit hibernate.jar readable ist.
Ein JAR kann nur (unverändert) migriert werden, wenn es keine Package-Überschneidungen mit anderen Modulen gibt (sonst Split-Package)!
Module-Path
java.base
java.sql
b c
The Unnamed Module
main.jar
hibernate.jar
b.jar
Copyright © Accso – Accelerated Solutions GmbH 62
Schritt 3: Third-Party-Lib in Automatic Module migrieren
hibernate wird in ein Automatic Module migriert.
Um hibernate auch noch in ein Explicit Module zu migrieren, müsste eine module-info erstellt werden. Machbar, aber: Aufwändig, benötigt Sourcen & Build, erstellt Fork plus Abhängigkeiten
Module-Path
java.base
java.sql
cb
hibernate
The Unnamed Module
main.jar
hibernate.jar
Copyright © Accso – Accelerated Solutions GmbH 63
Schritt 4: Automatic Module in Explicit Module migrieren
b kann nun in ein Explicit Module migriert werden, weil hibernate nun ebenfalls im Module-Path liegt.
Module-Path
java.base
java.sql
cb
hibernate
b
The Unnamed Module
main.jar
Copyright © Accso – Accelerated Solutions GmbH 64
Schritt 5: Den Rest migrieren
Module-Path
java.base
java.sql
c
junit
bmain
Module-Path
java.base
java.sql
c
hibernate
b
mainmain
The Unnamed Module
main.jar
Copyright © Accso – Accelerated Solutions GmbH 66
Auslesen der Module-Informationen aus JAR, aus module-info.class
Oder
Auslesen der Module-Informationen aus JMOD-Datei
Auslesen der Module-Informationen einer module-info.class - Datei
Module-Informationen auslesen
jar --file mlib/modmain.jar --print-module-descriptor
jdeps --module-path mlib mlib/modmain.jar
jmod describe java.base.jmod
javap -verbose module-info.class
Copyright © Accso – Accelerated Solutions GmbH 67
Module-Info aus einem „normalen JAR“ generierenz.B. für JAR-File junit-4.12.jar (und abhängiger JARs)
jdeps --gen-module-info ./gensrc -s amlib/*.jar
module junit { // Module-Name "junit" automatisch aus junit-4.12.jarrequires public hamcrest.core;requires java.management;
exports junit.extensions; // es werden *alle* Packages exportiertexports junit.framework;exports junit.runner;exports junit.textui;exports org.junit;exports org.junit.experimental;
... exports org.junit.runners.model;exports org.junit.runners.parameterized;exports org.junit.validator;
}
Copyright © Accso – Accelerated Solutions GmbH 68
java.lang.module
ModuleFinder
ModuleDescriptor
ModuleDescriptor.Requires
ModuleDescriptor.Exports
ModuleReference
Configuration
ModuleLayer
Zugriff auf das Modulsystem über neue APIs
Ein/alle Module finden („Observable Modules”)
Modulbeschreibung mit Name, Version, …
... mit allen Requires
... mit allen Exports
Laufzeit-Referenz auf ein Modul
„Was geladen wird“
java.lang.module.…
java.lang.reflect.…
Reflection-Support
Copyright © Accso – Accelerated Solutions GmbH 69
API: Module finden
Set<ModuleDescriptor> allModDescs = new HashSet<>();String modulePath = "/jigsaw/example/mlib";
// search all modules in module pathModuleFinder.of(Paths.get(modulePath))
.findAll()
.stream()
.filter (modRef -> modRef.descriptor().name().startsWith("de"))
.forEach(modRef -> { allModDescs.add(modRef.descriptor()); });
// search all system modulesModuleFinder.ofSystem()
.findAll()
.stream()
.filter (modRef -> !modRef.descriptor().name().startsWith("jdk"))
.forEach(modRef -> { allModDescs.add(modRef.descriptor()); });
Copyright © Accso – Accelerated Solutions GmbH 70
API: Module finden … und Infos ausgeben
allModDescs.stream().sorted().forEach(mod -> {
// print the module name and version and is-automatic?System.out.println( "Module " + mod.toNameAndVersion() );
// print the module's requiresmod.requires().stream().sorted()
.forEach((Requires req) -> { System.out.println( " requires " + req.name()); });
// print the module's exports (and targets of exports-to)mod.exports().stream()
.sorted(Comparator.comparing(Exports::source))
.forEach((Exports exp) -> { System.out.println( " exports " + exp.source()
+ " to " + exp.targets().toString()); });});
Copyright © Accso – Accelerated Solutions GmbH 71
java.activation@9-ea java.annotations.common@9-ea java.base@9-ea java.compact1@9-ea java.compact2@9-ea java.compact3@9-ea java.compiler@9-ea java.corba@9-ea java.datatransfer@9-ea java.desktop@9-ea java.httpclient@9-ea java.instrument@9-ea java.jnlp@9-ea java.logging@9-ea java.management@9-ea java.naming@9-ea java.prefs@9-ea java.rmi@9-ea java.scripting@9-ea java.se@9-ea java.se.ee@9-ea java.security.jgss@9-ea java.security.sasl@9-ea java.smartcardio@9-ea java.sql@9-ea java.sql.rowset@9-ea java.transaction@9-ea java.xml@9-ea java.xml.bind@9-ea java.xml.crypto@9-ea java.xml.ws@9-ea
Liste der 31 System-Module (mit Präfix „java.“)
im Build 9-ea+127-jigsaw-nightly-h5308-20160721
Copyright © Accso – Accelerated Solutions GmbH 72
„DepVis“: Tool zur Visualisierung eines Modul-Graphen
Ideen: req-public (n-transitiv), Filter auf einzelne Beziehungen,
Uses/Provides, 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
DepVis kann visualisieren:
… Modules im Module-Path
… Modules im System
… mit Black- & Whitelisting
… Explicit Modules und Automatic Modules
… requires, requires-public (1-transitiv), requires-mandated, exports-to
Copyright © Accso – Accelerated Solutions GmbH 74
Module java.desktop@9-earequires java.base [MANDATED]requires java.datatransfer [PUBLIC]requires java.prefsrequires java.xml [PUBLIC]
exports java.appletexports java.awt....exports java.beans....exports javax.accessibilityexports javax.imageio....exports javax.print....exports javax.sound....exports javax.swing....
exports com.sun.media.sound to [jdk.plugin, jdk.javaws]exports java.awt.dnd.peer to [javafx.swing]exports java.awt.peer to [jdk.plugin]exports sun.applet to [jdk.plugin]exports sun.applet.resources to [jdk.plugin]exports sun.awt to [jdk.plugin, javafx.swing, jdk.accessibility, jdk.javaws, jdk.deploy]exports sun.awt.dnd to [javafx.swing]exports sun.awt.image to [jdk.plugin, javafx.swing, jdk.javaws]exports sun.awt.windows to [jdk.plugin]exports sun.java2d to [javafx.swing]exports sun.swing to [jdk.plugin, javafx.swing]
java.desktop
4 requires
50 exports
11 exports-to an andere System-Module
Copyright © Accso – Accelerated Solutions GmbH 75
Module java.base@9-eaexports java.ioexports java.lang....exports java.mathexports java.net....exports java.nio....exports java.security....exports java.text....exports java.time....exports java.util....exports javax.crypto....exports javax.net....exports javax.net.sslexports javax.security....
exports com.sun.net.ssl.internal.ssl to [jdk.deploy]exports com.sun.security.ntlm to [java.security.sasl]exports jdk.internal to [jdk.jfr]exports jdk.internal.jimage to [jdk.jlink]exports jdk.internal.jimage.decompressor to [jdk.jlink]exports jdk.internal.loader to [java.instrument]exports jdk.internal.logger to [java.logging]exports jdk.internal.math to [java.desktop]exports jdk.internal.misc to [java.rmi, java.sql, jdk.charsets, java.logging, java.management, java.xml, jdk.jfr, jdk.jlink, jdk.unsupported, jdk.javaws, jdk.scripting.nashorn, jdk.deploy, java.security.jgss, jdk.net, java.desktop,
java.naming, javafx.graphics, jdk.vm.ci, jdk.plugin, jdk.compiler, jdk.jartool, java.corba]exports jdk.internal.module to [jdk.dynalink, java.management, java.xml, jdk.jfr, jdk.jlink, jdk.jartool, java.instrument]exports jdk.internal.org.objectweb.asm to [jdk.jfr, jdk.jlink, jdk.scripting.nashorn, jdk.vm.ci, java.instrument]exports jdk.internal.org.objectweb.asm.commons to [jdk.jfr, java.instrument, jdk.scripting.nashorn]exports jdk.internal.org.objectweb.asm.signature to [jdk.scripting.nashorn]exports jdk.internal.org.objectweb.asm.tree to [jdk.jfr, jdk.jlink, java.instrument]exports jdk.internal.org.objectweb.asm.tree.analysis to [jdk.jlink]exports jdk.internal.org.objectweb.asm.util to [jdk.jfr, jdk.jlink, jdk.scripting.nashorn, java.instrument]exports jdk.internal.org.xml.sax to [jdk.jfr]
...exports sun.util.logging to [javafx.base, java.desktop, javafx.controls, javafx.graphics, javafx.fxml, java.logging, java.prefs, javafx.swing]exports sun.util.resources to [jdk.localedata]
java.base
0 requires
51 exports
64 exports-to an andere System-Module
Copyright © Accso – Accelerated Solutions GmbH 76
Eclipse 4.6 plus Java9-Plugin (BETA):
• Eclipse startet mit Java 9
• module-info: Das meiste wird erkannt (aber z.B. kein „exports dynamic“).Sichtbarkeiten werden erkannt.Code-Completion für requires-Module, exports-Packages
• Es fehlt: Launch-Einstellungen für Module-Path, Automatic Modules, ....
Mühsame Pflege wird hoffentlich durch IDEs und Build-Tools erledigt:
• requires-Pflege Maven-POM Eclipse-.classpath
• exports -Pflege Package-Konventionen wie „…internal“ (?)
• Alle Kommandozeilenoptionen für javac und java
Maven, Gradle, Netbeans bieten erste Unterstützung für Java 9 (siehe Quality Outreach Programm des OpenJDK)
Wie steht‘s um Tools?
Copyright © Accso – Accelerated Solutions GmbH 77
Tools mit Java 9: Quality Outreach Programm des OpenJDKhttps://wiki.openjdk.java.net/display/quality/Quality+Outreach
Copyright © Accso – Accelerated Solutions GmbH 78
Java-Launcher mit einigen nützlichen Optionen:
Debugger kann Module-Informationen ausgeben, über Class.getModule()
Stacktraces geben Module-Informationen aus:
Debugging
pkgb.MyException: MyException's messageat pkgb.B.doItThrowException(modb/B.java:13)at pkgmain.Main.main(modmain/Main.java:18)
java --list-modules ...
java -Xdiag:resolver ...
java -Xlog:modules=debug|trace ...
Copyright © Accso – Accelerated Solutions GmbH 80
… und viele weitere Themen in Java 9 (zu wenig Zeit ;-)
Module und JavaDoc
Module und Annotations
Modifier von Requires , Exports Mandated, Synthetic, Public, …
ClassLoader hat sich im Grundprinzip nicht geändert
Layer Kapselung von Modulen zur Laufzeit
-Xbootclasspath fällt weg
Upgradeable Modules i.W. der Ersatz für Extension-Mechanismus
Nutzung von jlink für Linking von optimierten Runtime-Images
JEP238 für Multi-Release-JAR-Files JAR-File mit Java-Release-spezifischen Versionen
JMOD-Format und -Dateien i.W. JARs mit Native-Code usw.
Neuer Versionsstring in Java9 u.a. fällt Präfix „1.“ endlich weg
Instrumentierung geht nicht mehr für sehr früh geladenen Code
sun.misc.Unsafe nun in jdk.internal.misc.Unsafe
Copyright © Accso – Accelerated Solutions GmbH 81
http://openjdk.java.net/projects/jigsaw/
https://jdk9.java.net/jigsaw/
http://openjdk.java.net/projects/jigsaw/spec/reqs/
http://openjdk.java.net/projects/jigsaw/spec/issues/
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 NachlesenHomepage Project Jigsaw
Build
Specification
Diskussionsseite
State of the Module System
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
Copyright © Accso – Accelerated Solutions GmbH 82
204 to go! Roadmap bis Java 9
Early Draft Review 9/2016
Public Review 11/2016
Proposed Final Draft 1/2017
Final Release 3/2017
Roadmap bis Java 9http://openjdk.java.net/projects/jdk9/
2016/05/26 Feature Complete
2016/08/11 All Tests Run
2016/09/01 Rampdown Start
2016/10/20 Zero Bug Bounce
2016/12/01 Rampdown Phase2
2017/01/26 Final Rel.Candidate
2017/03/23 General Availability
Roadmap für den JSR 376 (aus der Mailingliste)
Copyright © Accso – Accelerated Solutions GmbH 84
Jigsaw ist noch nicht fertig (?), Diskussionen u.a. noch zu …
Exporte nur zur Laufzeit, v.a. für Reflection („exports dynamic“)?
Module-Abhängigkeiten nur zur Compile-Zeit („requires static“)?
Laufzeit-Beziehungen lazy auflösen?
Annotations für Module?
Deprecation für Module?
> 1 Module in 1 JAR (so wie Fat-JARs), dazu Multi-Release-JARs?
...
Teilweise sehr fundamentale Kritik auf den Mailinglisten.
Copyright © Accso – Accelerated Solutions GmbH 85
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 …
Copyright © Accso – Accelerated Solutions GmbH 86
Kritik … und Lob
Ein Module hat keine (echten) Versionen - nur informell
Kein Alias für ein Module möglich außer --patch-module
Modules sind nicht gruppierbar. Keine Hierarchie (vgl. Maven parent.pom)Gut: Aggregator-Module über requires-public
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?
Copyright © Accso – Accelerated Solutions GmbH 87
Aus der Mailingliste zu „warum module-info als .class?“
Copyright © Accso – Accelerated Solutions GmbH 88
Der richtige Schritt zur echter Komponentenorientierung!
Jigsaw und Java 9 sind sehr stabil.
Mit Eclipse kann man bereits jetzt halbwegs arbeiten.
Migration ist machbar, aber wird mühsam!
• Module-Kategorien: „wo kommt was her?“ ist nicht trivial!
• MP & CP: Bekommen wir das jemals richtig aussortiert?
• Observable != Configuration ClassNotFoundExceptionNimm-Alles-Schalter --add-modules ALL-MODULE-PATH
… und Lob!
Copyright © Accso – Accelerated Solutions GmbH 9090 Copyright © Accso GmbH
Accso – Accelerated Solutions GmbHwww.accso.detwitter.com/accso
Berliner Allee 5864295 DarmstadtTelefon: +49 (6151) 13029-0Fax: +49 (6151) 13029-10
Moltkestraße 131 a50674 KölnTelefon: +49 (221) 630691-0Fax: +49 (221) 630691-10
Theatinerstraße 1180333 MünchenTelefon: +49 (89) 71042-2040Fax: + 49 (89) 71042-2001
90
@lemmi111171
de.slideshare.net/lemmi
www.xing.com/profile/Martin_Lehmann3
www.xing.com/profile/Kristine_Schaal
MartinLehmann1971
kristines
accsohttps://github.com/accso/java9-jigsaw-examples/
@accso
Copyright © Accso – Accelerated Solutions GmbH 91
SHARING YOURCHALLENGE
91 Copyright © Accso GmbH
Accso – Accelerated Solutions GmbHwww.accso.detwitter.com/accso
Berliner Allee 5864295 DarmstadtTelefon: +49 (6151) 13029-0Fax: +49 (6151) 13029-10
Moltkestraße 131 a50674 KölnTelefon: +49 (221) 630691-0Fax: +49 (221) 630691-10
Theatinerstraße 1180333 MünchenTelefon: +49 (89) 71042-2040Fax: + 49 (89) 71042-2001
91