Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
Migrating to Java 9
Modules
By Sander Mak
@Sander_Mak
Migrating to Java 9
Java 8
java -cp .. -jar myapp.jar
Migrating to Java 9
Java 8
java -cp .. -jar myapp.jar
Java 9
java -cp .. -jar myapp.jar
Today's journey
Running on Java 9
Java 9 modules
Migrating to modules
Modularising code
Migrating to Java 9
Java 8
java -cp .. -jar myapp.jar
Java 9
java -cp .. -jar myapp.jar
Let's try it!
Classpath migration problems
‣
‣
Unresolved platform modules
(Ab)use of platform internals
Missing platform modules
import javax.xml.bind.DatatypeConverter;
public class Main {
}
public static void main(String... args) {
DatatypeConverter.parseBase64Binary("SGVsbG8gd29ybGQh");
}
error: package javax.xml.bind does not exist
Modular JDK
Modular JDK
Modular JDK
Modular JDK
Modular JDK
Missing platform modules
‣
Classpath compile-time
“java.se” module is used
‣
This does not resolve:
java.activation
java.corba
java.transaction
java.xml.bind
java.xml.ws
java.xml.ws.annotation
Add unresolved platform modules
Find
jdeps demo/Main.class
Main.class -> java.base
Main.class -> not found
<unnamed>
-> java.lang
<unnamed>
-> javax.xml.bind
java.base
not found
Add unresolved platform modules
Find
jdeps demo/Main.class
Main.class -> java.base
Main.class -> not found
<unnamed>
-> java.lang
<unnamed>
-> javax.xml.bind
Fix
java.base
not found
javac --add-modules java.xml.bind demo/Main.java
Add unresolved platform modules
Find
jdeps demo/Main.class
Main.class -> java.base
Main.class -> not found
<unnamed>
-> java.lang
<unnamed>
-> javax.xml.bind
Fix
java.base
not found
javac --add-modules java.xml.bind demo/Main.java
java --add-modules java.xml.bind demo/Main.java
Add unresolved platform modules
javac --add-modules java.xml.bind demo/Main.java
java --add-modules java.xml.bind demo/Main.java
Let's try it!
Using encapsulated APIs
public class Main {
}
public static void main(String... args) throws Exception {
sun.security.x509.X500Name name =
new sun.security.x509.X500Name("CN=user");
}
Using encapsulated APIs
public class Main {
}
public static void main(String... args) throws Exception {
sun.security.x509.X500Name name =
new sun.security.x509.X500Name("CN=user");
}
Main.java:4: error: package
sun.security.x509 does not exist
sun.security.x509.X500Name name =
^
Use jdeps to find problems
jdeps -jdkinternals Main.class
Main.class -> java.base
Main
-> sun.security.x509.X500Name
JDK Internal API
---------------sun.security.x509.X500Name
JDK internal API (java.base)
Suggested Replacement
--------------------Use javax.security.auth.x500.X500Principal
@since 1.4
Using encapsulated APIs
Compile with 1.8, run with 9:
Using encapsulated APIs
Compile with 1.8, run with 9:
Exception in thread "main" java.lang.IllegalAccessError: class Main
(in unnamed module @0x4cdbe50f) cannot access class
sun.security.x509.X500Name (in module java.base) because module
java.base does not export sun.security.x509 to unnamed module
@0x4cdbe50f
at Main.main(Main.java:4)
Using encapsulated APIs
Compile with 1.8, run with 9:
Exception in thread "main" java.lang.IllegalAccessError: class Main
(in unnamed module @0x4cdbe50f) cannot access class
sun.security.x509.X500Name (in module java.base) because module
java.base does not export sun.security.x509 to unnamed module
@0x4cdbe50f
at Main.main(Main.java:4)
java --add-exports java.base/sun.security.x509=ALL-UNNAMED Main
Using encapsulated APIs
Compile with 1.8, run with 9:
Exception in thread "main" java.lang.IllegalAccessError: class Main
(in unnamed module @0x4cdbe50f) cannot access class
sun.security.x509.X500Name (in module java.base) because module
java.base does not export sun.security.x509 to unnamed module
@0x4cdbe50f
at Main.main(Main.java:4)
New 'kill-switch':
java --permit-illegal-access Main
Back to Modules...
Mental picture of your app
main
books.api
books.impl
bookstore
Actual view of your app
Java 9 modules make this possible!
main
books.api
books.impl
bookstore
Migrating to modules
Top down migration
commons.lang3.3.4.jar
demonstrator.jar
java.base
classpath
module path
Classic classpath
package com.javamodularity.demonstrator;
import org.apache.commons.lang3.StringUtils;
public class Demo {
}
public static void main(String args[]) {
String output = StringUtils.leftPad("Leftpad FTW!", 20);
System.out.println(output);
}
Classic classpath
package com.javamodularity.demonstrator;
import org.apache.commons.lang3.StringUtils;
public class Demo {
}
Compile
Run
public static void main(String args[]) {
String output = StringUtils.leftPad("Leftpad FTW!", 20);
System.out.println(output);
}
javac -cp lib/commons-lang3-3.4.jar
-d out $(find src -name '*.java')
java -cp out:lib/commons-lang3-3.4.jar
com.javamodularity.demonstrator.Demo
Top down migration
commons.lang3.3.4.jar
demonstrator.jar
java.base
classpath
module path
Top down migration
commons.lang3.3.4.jar
Can’t reference the classpath
from named modules!
classpath
demonstrator.jar
java.base
module path
Top down migration
classpath
commons.lang
demonstrator.jar
But this isn’t our code!
java.base
module path
Automatic Modules
‣
A plain JAR on the module path becomes an
Automatic Module
‣
‣
‣
Module name derived from JAR name
Exports everything
Reads all other modules
Using Automatic Modules
module demonstrator {
requires commons.lang;
}
Using Automatic Modules
module demonstrator {
requires commons.lang;
}
Compile
Run
javac --module-path lib
--module-source-path src
-d mods $(find src -name '*.java')
java --module-path mods:lib
-m demonstrator/com.javamodularity.demonstrator.Demo
Migrating the books app
Step 2
Create a “monolith module”
2. Declare exports
3. Figure out “requires”
4. Move some libs to Automatic Modules
1.
commons.pool
commons.logging
hsqldb
spring.core
spring.orm
spring.beans
classpath
spring.aop
…
spring.context
javax.inject
Application code
spring.tx
hibernate.core
hibernate.jpa
module path
Automatic modules
Named modules
commons.pool
commons.logging
hsqldb
spring.core
spring.orm
spring.beans
classpath
spring.aop
…
spring.context
javax.inject
Application code
spring.tx
hibernate.core
hibernate.jpa
module path
Automatic modules
Named modules
DEMO
Open Modules
‣ Reliable configuration like normal modules
‣ Requires for every dependency
‣ Opens all packages for deep reflection
‣
‣
Easy compatibility with existing code and frameworks
Allows reflection
Type
Compile time
Reflection on public
Deep reflection
Exports
✓
✓
✘
Open
✘
✓
✓
Exports + Open
✓
✓
✓
Open Packages
Opens the package for deep reflection, but not compile
time access
A package can be both open and exported
Tip 1
Move libraries to module path one by one
Start with direct dependencies
Tip 2
open when no compile time dependency
should exist (possibly qualified)
Tip 3
requires only for direct dependencies
--add-modules for run-time dependencies
Tip 4
Use open modules for framework compatibility
Fine tune open later
Migrating the books app
Step 3
Split monolith module
2. Move requires/exports
3. (optional) Move config files
1.
commons.pool
commons.logging
hsqldb
spring.core
spring.orm
spring.beans
classpath
spring.aop
…
spring.context
javax.inject
Application code
spring.tx
hibernate.core
hibernate.jpa
module path
Automatic modules
Named modules
commons.pool
commons.logging
hsqldb
spring.core
spring.orm
spring.beans
classpath
spring.aop
…
spring.context
javax.inject
main
spring.tx
hibernate.core
module path
books.api
books.impl
bookstore
hibernate.jpa
Automatic modules
Named modules
Migration steps - recap
Migration steps - recap
‣
Migrate to Java 9 using classpath only
Migration steps - recap
‣
Migrate to Java 9 using classpath only
‣
Create a module around your whole app
Migration steps - recap
‣
Migrate to Java 9 using classpath only
‣
Create a module around your whole app
‣
Modularize your application!
Thank you.
code @ bit.ly/java9mig
bit.ly/java9book
@javamodularity
Thank you.
code @ bit.ly/java9mig
Java 9 Modularity: First Look
bit.ly/java9book
@javamodularity
http://bit.ly/java9course