Java 9: modularity &
migration issues
Oleh Krupenia
Senior Software Engineer, Consultant
Agenda
1. What is Project Jigsaw;
2. Which benefits does modularity bring;
3. module-info.java contents;
4. Which migration issues can be and how to resolve them;
5. Let’s migrate a small project to Java 9
2
Release GA Date End of Public
Updates
8 Mar 2014 Jan 2019
9 Sep 2017 Mar 2018
10 (18.3) Mar 2018 Sep 2018
11(18.9 LTS) Sep 2018 TBA
3
Project Jigsaw
4
Project Jigsaw
5
Module
A uniquely named, reusable group of related packages, as well as resources
(such as images and XML files) and a module descriptor specifying:
- the module’s name
- the module’s dependencies
- the packages it explicitly makes available to other modules
- the services it offers
- the services it consumes
- to what other modules it allows reflection
6
Module
module com.foo {
requires com.google.common;
}
7
Advantages
- Improved encapsulation
- Better security
- Easier construction and maintenance of large
applications
- Performance
8
Access levels
- public to everyone
- public to specific modules
- public within current module
- protected
- package
- private
9
10
JDK 8
bin
*.exe
jre lib
tools.jar
bin
*.exe
lib
rt.jar
11
JDK 8 JDK 9
bin
*.exe
jre lib
tools.jar
bin
*.exe
lib
rt.jar
bin
*.exe
conf libjmods
12
JEP 260: Encapsulate Most
Internal APIs
Public
- java.*
- javax.*
- com.sun.*
Internal API – sun.*
13
JEP 260: Encapsulate Most
Internal APIs
Internal API
- non-critical
sun.misc.BASE64Decoder
- critical
sun.misc.Unsafe
14
--module-path --classpath
Modular JAR application module unnamed module
Non-Modular JAR automatic module unnamed module
--module-path
15
Type Origin Exports packages Can read modules
Platform provided by JDK explicitly -
Application any JAR containing
module-info.class
on the module path
explicitly platform
application
automatic
Automatic any JAR without
module-info.class
on the module path
all platform
application
automatic
unnamed
Unnamed all JARs and classes
on the classpath
all platform
application
automatic
Module readability
16
Requires
A requires module directive specifies that this
module depends on another module.
module com.foo {
requires com.google.common;
requires transitive com.foo.bar;
}
17
exports and exports…to
An exports module directive specifies one of the
module’s packages whose public types (and their
nested public and protected types) should be
accessible to code in all other modules.
module com.foo {
requires com.google.common;
exports com.baz;
exports com.bar to foo.bar;
}
18
provides…with
A provides … with module directive specifies that a
module provides a service implementation—making
the module a service provider.
module com.foo {
requires com.google.common;
exports com.foo;
provides com.google.common.collect.BiMap
with com.foo.TestBiMap;
}
19
uses
A uses module directive specifies a service used by this
module—making the module a service consumer. A
service is an object of a class that implements the
interface or extends the abstract class specified in the
uses directive.
module foo.bar {
requires com.google.common;
uses com.google.common.collect.BiMap;
}
20
opens, opens ... to
Before Java 9, reflection could be used to learn about
all types in a package and all members of a type—even
its private members—whether you wanted to allow this
capability or not. Thus, nothing was truly encapsulated.
module foo.bar {
requires com.google.common;
opens com.foo to foo.bar;
open com.foo
}
21
22
Migration issues
Linking
22
Migration issues
23
The underscore character ("_") is not
valid identifier
Error: as of release 9, '_' is a keyword, and may not be
used as a legal identifier.
JEP 302: Lambda Leftovers
BiFunction<Integer, String, String> biss = (i, _) ->
String.valueOf(i);
24
Removed GC Options
The following GC combinations will cause your
application to fail to start in JDK 9:
- DefNew + CMS
- ParNew + SerialOld
- Incremental CMS
25
Use CLDR Locale Data by Default
In JDK 9, the Unicode Consortium’s Common Locale Data
Repository (CLDR) data is enabled as the default locale data.
Code that uses locale-sensitive services such as date, time,
and number formatting may produce different results with the
CLDR locale data. Remember that even
System.out.printf() is locale-aware.
26
-source and -target
In JDK 8, -source and -target values of 1.5/5 and
earlier were deprecated and caused a warning to be
generated. In JDK 9, those values cause an error.
If possible, use the new --release flag instead of the -
source and -target options.
27
Removed java.* APIs
java.* APIs that have been removed in JDK 9 include the
previously deprecated methods from the
java.util.logging.LogManager and java.util.jar.Pack200 packages:
java.util.logging.LogManager.addPropertyChangeListener
java.util.logging.LogManager.removePropertyChangeListener
java.util.jar.Pack200.Packer.addPropertyChangeListener
java.util.jar.Pack200.Packer.removePropertyChangeListener
28
java.awt.peer Not Accessible
The java.awt.peer and java.awt.dnd.peer packages
aren’t accessible in JDK 9. The packages were never
part of the Java SE API, despite being in the java.*
namespace.
Replace this with Component.isDisplayable()
29
Removed com.sun.image.codec.jpeg
Package
The nonstandard package com.sun.image.codec.jpeg
has been removed.
Use the Java Image I/O API instead.
30
Removed Tools Support for Compact
Profiles
Profiles, introduced in Java SE 8, define subsets of the Java SE
Platform API that can reduce the static size of the Java runtime
on devices that have limited storage capacity.
In JDK 9, the -profile option is supported by javac only in
conjunction with the --release 8 option, and isn’t supported
by java.
31
Access To Internal APIs
If you must use an internal API that has been made
inaccessible by default, then you can break encapsulation
using the --add-exports command-line option.
The syntax of the --add-exports option is:
--add-exports <source-module>/<package>=<target-
module>(,<target-module>)*
32
Access To Internal APIs
where <source-module> and <target-module> are
module names and <package> is the name of a
package.
--add-exports
java.management/sun.management=ALL-UNNAMED
33
Run jdeps on Your Code
Run the jdeps tool on your application to see what
packages and classes your applications and libraries
depend on.
34
Run jdeps on Your Code
> jdeps guava-20.0.jar
guava-20.0.jar -> java.base
guava-20.0.jar -> java.logging
guava-20.0.jar -> jdk.unsupported
com.google.common.annotations -> java.base
com.google.common.base -> java.logging
com.google.common.cache -> JDK internal API
35
--add-opens
If you have to allow code on the class path to do deep
reflection to access non public members, then use the --add-
opens runtime option.
--add-opens module/package=target-module(,target-module)*
--add-opens java.management/sun.management=ALL-
UNNAMED
36
Dependencies On Java EE Modules
In JDK 9, the modules that contain CORBA or the APIs
shared between Java SE and Java EE are not resolved by
default when you compile or run code on the class path.
37
Dependencies On Java EE Modules
java.corba — CORBA
java.transaction — The subset of the Java Transaction API to support
CORBA Object Transaction Services
java.activation — JavaBeans Activation Framework
java.xml.bind — Java Architecture for XML Binding (JAXB)
java.xml.ws — Java API for XML Web Services (JAX-WS), Web Services
Metadata for the Java Platform, and SOAP with Attachments for Java
(SAAJ)
java.xml.ws.annotation — The subset of the JSR-250 Common
Annotations to support web services
38
Dependencies On Java EE Modules
1. Use the --add-modules command-line option to ensure that
the module with the API is resolved at startup. For example,
specify --add-module java.xml.bind to ensure that the
java.xml.bind module is resolved.
1. Deploy the standalone version of the API (and implementation
if needed) on the class path. Each of the Java EE APIs are
standalone technologies with projects published in Maven
Central.
39
Split packages
Module is not allowed to read the same package from two
different modules.
Possible solutions:
1. Rename packages
2. The option --patch-module $module=$artifact will merge all
classes from $artifact into $module
3. Combine the two jars into a single jar
4. Use unnamed modules
40
Example
41
Questions?
42
Thank you!
oleh.krupenia@globallogic.com

Java 9: Deep Dive into Modularity and Dealing with Migration Issues

  • 1.
    Java 9: modularity& migration issues Oleh Krupenia Senior Software Engineer, Consultant
  • 2.
    Agenda 1. What isProject Jigsaw; 2. Which benefits does modularity bring; 3. module-info.java contents; 4. Which migration issues can be and how to resolve them; 5. Let’s migrate a small project to Java 9 2
  • 3.
    Release GA DateEnd of Public Updates 8 Mar 2014 Jan 2019 9 Sep 2017 Mar 2018 10 (18.3) Mar 2018 Sep 2018 11(18.9 LTS) Sep 2018 TBA 3
  • 4.
  • 5.
  • 6.
    Module A uniquely named,reusable group of related packages, as well as resources (such as images and XML files) and a module descriptor specifying: - the module’s name - the module’s dependencies - the packages it explicitly makes available to other modules - the services it offers - the services it consumes - to what other modules it allows reflection 6
  • 7.
    Module module com.foo { requirescom.google.common; } 7
  • 8.
    Advantages - Improved encapsulation -Better security - Easier construction and maintenance of large applications - Performance 8
  • 9.
    Access levels - publicto everyone - public to specific modules - public within current module - protected - package - private 9
  • 10.
  • 11.
  • 12.
    JDK 8 JDK9 bin *.exe jre lib tools.jar bin *.exe lib rt.jar bin *.exe conf libjmods 12
  • 13.
    JEP 260: EncapsulateMost Internal APIs Public - java.* - javax.* - com.sun.* Internal API – sun.* 13
  • 14.
    JEP 260: EncapsulateMost Internal APIs Internal API - non-critical sun.misc.BASE64Decoder - critical sun.misc.Unsafe 14
  • 15.
    --module-path --classpath Modular JARapplication module unnamed module Non-Modular JAR automatic module unnamed module --module-path 15
  • 16.
    Type Origin Exportspackages Can read modules Platform provided by JDK explicitly - Application any JAR containing module-info.class on the module path explicitly platform application automatic Automatic any JAR without module-info.class on the module path all platform application automatic unnamed Unnamed all JARs and classes on the classpath all platform application automatic Module readability 16
  • 17.
    Requires A requires moduledirective specifies that this module depends on another module. module com.foo { requires com.google.common; requires transitive com.foo.bar; } 17
  • 18.
    exports and exports…to Anexports module directive specifies one of the module’s packages whose public types (and their nested public and protected types) should be accessible to code in all other modules. module com.foo { requires com.google.common; exports com.baz; exports com.bar to foo.bar; } 18
  • 19.
    provides…with A provides …with module directive specifies that a module provides a service implementation—making the module a service provider. module com.foo { requires com.google.common; exports com.foo; provides com.google.common.collect.BiMap with com.foo.TestBiMap; } 19
  • 20.
    uses A uses moduledirective specifies a service used by this module—making the module a service consumer. A service is an object of a class that implements the interface or extends the abstract class specified in the uses directive. module foo.bar { requires com.google.common; uses com.google.common.collect.BiMap; } 20
  • 21.
    opens, opens ...to Before Java 9, reflection could be used to learn about all types in a package and all members of a type—even its private members—whether you wanted to allow this capability or not. Thus, nothing was truly encapsulated. module foo.bar { requires com.google.common; opens com.foo to foo.bar; open com.foo } 21
  • 22.
  • 23.
  • 24.
    The underscore character("_") is not valid identifier Error: as of release 9, '_' is a keyword, and may not be used as a legal identifier. JEP 302: Lambda Leftovers BiFunction<Integer, String, String> biss = (i, _) -> String.valueOf(i); 24
  • 25.
    Removed GC Options Thefollowing GC combinations will cause your application to fail to start in JDK 9: - DefNew + CMS - ParNew + SerialOld - Incremental CMS 25
  • 26.
    Use CLDR LocaleData by Default In JDK 9, the Unicode Consortium’s Common Locale Data Repository (CLDR) data is enabled as the default locale data. Code that uses locale-sensitive services such as date, time, and number formatting may produce different results with the CLDR locale data. Remember that even System.out.printf() is locale-aware. 26
  • 27.
    -source and -target InJDK 8, -source and -target values of 1.5/5 and earlier were deprecated and caused a warning to be generated. In JDK 9, those values cause an error. If possible, use the new --release flag instead of the - source and -target options. 27
  • 28.
    Removed java.* APIs java.*APIs that have been removed in JDK 9 include the previously deprecated methods from the java.util.logging.LogManager and java.util.jar.Pack200 packages: java.util.logging.LogManager.addPropertyChangeListener java.util.logging.LogManager.removePropertyChangeListener java.util.jar.Pack200.Packer.addPropertyChangeListener java.util.jar.Pack200.Packer.removePropertyChangeListener 28
  • 29.
    java.awt.peer Not Accessible Thejava.awt.peer and java.awt.dnd.peer packages aren’t accessible in JDK 9. The packages were never part of the Java SE API, despite being in the java.* namespace. Replace this with Component.isDisplayable() 29
  • 30.
    Removed com.sun.image.codec.jpeg Package The nonstandardpackage com.sun.image.codec.jpeg has been removed. Use the Java Image I/O API instead. 30
  • 31.
    Removed Tools Supportfor Compact Profiles Profiles, introduced in Java SE 8, define subsets of the Java SE Platform API that can reduce the static size of the Java runtime on devices that have limited storage capacity. In JDK 9, the -profile option is supported by javac only in conjunction with the --release 8 option, and isn’t supported by java. 31
  • 32.
    Access To InternalAPIs If you must use an internal API that has been made inaccessible by default, then you can break encapsulation using the --add-exports command-line option. The syntax of the --add-exports option is: --add-exports <source-module>/<package>=<target- module>(,<target-module>)* 32
  • 33.
    Access To InternalAPIs where <source-module> and <target-module> are module names and <package> is the name of a package. --add-exports java.management/sun.management=ALL-UNNAMED 33
  • 34.
    Run jdeps onYour Code Run the jdeps tool on your application to see what packages and classes your applications and libraries depend on. 34
  • 35.
    Run jdeps onYour Code > jdeps guava-20.0.jar guava-20.0.jar -> java.base guava-20.0.jar -> java.logging guava-20.0.jar -> jdk.unsupported com.google.common.annotations -> java.base com.google.common.base -> java.logging com.google.common.cache -> JDK internal API 35
  • 36.
    --add-opens If you haveto allow code on the class path to do deep reflection to access non public members, then use the --add- opens runtime option. --add-opens module/package=target-module(,target-module)* --add-opens java.management/sun.management=ALL- UNNAMED 36
  • 37.
    Dependencies On JavaEE Modules In JDK 9, the modules that contain CORBA or the APIs shared between Java SE and Java EE are not resolved by default when you compile or run code on the class path. 37
  • 38.
    Dependencies On JavaEE Modules java.corba — CORBA java.transaction — The subset of the Java Transaction API to support CORBA Object Transaction Services java.activation — JavaBeans Activation Framework java.xml.bind — Java Architecture for XML Binding (JAXB) java.xml.ws — Java API for XML Web Services (JAX-WS), Web Services Metadata for the Java Platform, and SOAP with Attachments for Java (SAAJ) java.xml.ws.annotation — The subset of the JSR-250 Common Annotations to support web services 38
  • 39.
    Dependencies On JavaEE Modules 1. Use the --add-modules command-line option to ensure that the module with the API is resolved at startup. For example, specify --add-module java.xml.bind to ensure that the java.xml.bind module is resolved. 1. Deploy the standalone version of the API (and implementation if needed) on the class path. Each of the Java EE APIs are standalone technologies with projects published in Maven Central. 39
  • 40.
    Split packages Module isnot allowed to read the same package from two different modules. Possible solutions: 1. Rename packages 2. The option --patch-module $module=$artifact will merge all classes from $artifact into $module 3. Combine the two jars into a single jar 4. Use unnamed modules 40
  • 41.
  • 42.
  • 43.