Java 9 is just around the corner. In this session, we'll describe the new modularization support (Jigsaw), new JDK tools, enhanced APIs and many performance improvements that were added to the new version.
2. Java 9
• Java 9 brings many additions and improvements:
• Project Jigsaw and the new Module System.
• Reactive streams.
• New JDK tools (e.g., jshell).
• Minor syntax changes.
• JVM Enhancements.
3. Project Jigsaw
• With the rising of micro-services and docker containers, Java
applications face the burden of requiring the entire JRE.
• Very large in size.
• Most applications don’t actually need Swing or Java Sound.
• The goal of project Jigsaw is to divide the standard-libraries into
modules.
• You only use (provide) the modules you require (either directly
or transitive).
4. The Module System
• Modules provide a better encapsulation mechanism than the
available ones.
• Currently, we have the following:
• Classes – provide a good encapsulation but only “in the small”.
• Packages – provide almost nothing in encapsulation.
• JARs – Although well suited for encapsulation, currently there is no
support for it.
5. What about OSGi?
• Originated at 1999, OSGi provides a solution for modules in
Java by using a classloader-per-JAR approach.
• At its core, it solves the following:
• Encapsulation.
• Versioning.
• Dynamic updates.
6. What about OSGi?
• However, it requires a runtime framework (e.g., Equinoux).
• Complicates the development, testing and troubleshooting of
the application.
7. The Module System
• The new module system provides a simpler solution but doesn’t
solve all the problems that OSGi solves.
• Let’s see how it works…
8. The Module System
• A module encapsulates packages.
• I.e., you can control which packages will be exposed (exported)
to other modules.
• In you module you can also require other modules (not
packages).
• Done in a special module-info.java file.
• A module is wrapped in a JAR and must reside on the
modulepath!
9. Module Path
• Java 9 supports both classpath and modulepath!
• If a modular JAR is on the classpath, it will not be considered as
a module at all.
10. module-info.java
• New restricted keywords (only for this file):
module com.trainologic.example {
exports com.trainologic.example.api;
requires java.naming;
}
11. Qualified Exports
• You can also restrict a module usage to specific module/s.
• E.g.:
module com.trainologic.example {
exports com.trainologic.example.api to java.activation;
}
12. Requires Transitive
• You can follow the requires keyword with transitive, providing
transitive dependency.
• E.g.:
module com.trainologic.example {
requires transitive java.naming;
}
13. Requires Static
• You can follow the requires keyword with static, providing
optional (compile-time) dependency.
• E.g.:
module com.trainologic.example {
requires static java.naming;
}
14. Provides
• The provides restricted keyword indicates that the module
implements a Service Provider interface.
• E.g.,:
module java.naming {
provides java.security.Provider with sun.security.provider.certpath.ldap.JdkLDAP;
}
15. Uses
• The uses restricted keyword indicates that the module is using
a Service Provider interface.
• E.g.,:
module java.naming {
uses javax.naming.spi.InitialContextFactory;
}
16. jmod
• New packaging format.
• Currently based on zip files.
• Can hold native libraries and configuration files.
• JDK modules are packaged in this format.
• Can be used at compile-time and link-time but not in run-time.
18. Modular JDK
• At the base of everything there is: java.base.
• We usually don’t need javafx.web (~16M).
• Allows for small runtime images.
• What is runtime-image anyway?
19. Runtime Images
• You can create a custom runtime image using jlink.
• Optimizes the required JDK/JRE and custom modules to create
a custom runtime (only required modules).
• Also allow for whole-world optimizations which were impossible
to do at compile-time.
20. Reactive Streams
• A new addition to java.util.concurrent.
• Provide a set of standard interfaces to deal with asynchronous
stream processing with non-blocking back-pressure.
• I.e., notifying producers of data to reduce their message rate.
• Implemented in java.util.concurrent.Flow.
21. Interfaces
• Publisher – the producer. Provides a single method:
subscribe().
• Subscriber – subscribes to a Producer. Has the following
methods:
• onSubscribe – will be invoked before any other method.
• onNext – invoked with the next item to process.
• onError – unrecoverable error, no more methods will be invoked on this
instance.
• onComplete – no additional data will be receive (last method to be
invoked).
22. Interfaces
• Subscription – provided to the onSubscribe invocation. Provides
the following methods:
• request(n) – demands n more elements from the producer.
• cancel – best effort method to cancel the subscription.
• Processor – implements both Producer and Subscriber.
23. Reactive Streams
• The JDK doesn’t provide implementations for reactive-streams
interfaces.
• Available popular implementations:
• Project Reactor – used by Spring 5.
• Akka Streams.
• RxJava.
• Vert.x.
• Slick.
• MongoDB Java driver.
• Reactive Rabbit (RabbitMQ).
• Ratpack.
24. The Java Language
• Small additions:
• Private methods in interfaces.
• @SafeVarargs allowed on private methods.
• Generic type inference for anonymous classes.
• Underscore identifier name has been disallowed.
• Support for effectively-final variables in try-with-resources usage.
25. Generic Type Inference
• Diamond operator is now allowed also for anonymous classes:
public class WorksInJava9ButNot8 {
public static abstract class Example<T> {
public abstract T id(T t);
}
public static <T> T usage(T value, Example<T> ex) {
return ex.id(value);
}
public static void main(String[] args) {
String result = usage("hello", new Example<>() {
@Override
public String id(String s) {
return s;
}
});
}
}
26. Underscore
• Underscores are valid characters for identifier names.
• However, a variable name consisting of a single underscore has
been deprecated (warning) in Java 8.
• Removed completely in Java 9.
• Planned to be used for additional lambda syntax in Java 10.
27. @SafeVarargs
• Variable length parameters support can be problematic when
mixed with generics.
• E.g.: public static <T> T[] foo(T… param)
• Due to the fact that in some cases the compiler will create an
array of Object instead of a concrete type.
• The annotation can be put by the programmer to assure the
compiler that the implementation is safe.
• Now it is supported for private methods.
28. Try-with-Resources
• You can use effectively-final variables with ARM (Automatic-
Resource-Management):
Socket s = new Socket();
try(s) {
// will be closed automatically
}
29. Factory Collections Methods
• In Java 9, the standard collection library provides convenient
collections factory methods:
• Set.of(T… elements).
• Map.of(K,V,K,V…) up to 10 entries.
• Map.ofEntries(Entry … entries).
30. jshell
• Java has REPL now!
• REPL === Read-Evel-Print Loop.
• Based on standard API to evaluate “Java Snippets”.
31. jaotc
• Ahead-of-time compiler for Java.
• Currently only for Linux/x64.
• Brings the security of code IP.
• No easy dis-assemble.
• Not aimed at performance per se.
• Aimed for security and fast load-time (think grep utility).
32. MRJAR
• Multi-Release JARs.
• Supports providing multiple implementations for different JDKs.
• The MANIFEST.MF attribute: “Multi-Release” must be set to
true.
• In order to be backwards compatible, the oldest (default)
classes are put in the root of the JAR (as before).
• Java 9 and above implementations can reside in a version
specific directory.
34. MRJAR and Modules
• The module descriptor can be versioned.
• However, it can differ from the root-ed one (default) only by the
implementation (‘uses’ and transitive dependencies).
35. Default GC
• G1 becomes the default GC in Java 9 (instead of Mark &
Compact).
• Provides scalability for large heaps (regarding pauses).
• Easy configuration (compared to CMS).
• CMS is deprecated.
36. G1
• Introduced in JDK 7 update 4.
• Low-Latency collector.
• Good support for heaps larger than 4GB.
• Divides heap into regions (1MB to 32MB).
• Scans regions that contain the most garbage objects first.
• String deduplication starting in Java 8 (update 20).
38. String Compaction
• The String class supports compaction.
• I.e., can hold either UTF16 (the old encoding) or LATIN-1.
• No changes for API.
• Controlled by: -XX:+CompactStrings (default is true in Java 9).
39. Enhanced Deprecation
• The @Deprecated annotation, starting with Java 9, supports the
following attributres:
• since – a string defaults to “”.
• forRemoval – a boolean defaults to false.
• A new JDK tool: jdeprscan is provided to scan for deprecation
usage in JARs.
40. Serialization Filters
• New addition to Java Serialization and RMI to support filtering
on the receiver side.
• For example, we can add a filter to ObjectInputStream that will
disallow remote objects.
• In the filter you have access to the incoming object’s class,
depth, # of references and it’s array components.
41. StackWalker
• A new API to lazily traverse the current execution stack (based
on streams).
• Example:
public void foo1() {
foo2();
}
public void foo2() {
foo3();
}
public void foo3() {
List<String> frames = StackWalker.getInstance().walk(s ->
s.limit(3).map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
// prints [foo3, foo2, foo1] (without main)
System.out.println(frames);
}
public static void main(String[] args) {
new Scratch().foo1();
}
42. Spin Waiting
• In low-latency applications we sometimes do a busy-spin (e.g.,
the Disruptor framework).
• Java 9 provides a new method in the Thread class:
onSpinWait() that should be invoked on every busy-spin
iteration.
• Depends on the specific runtime, the JVM optimizer may use
architecture-specific instructions for spin loops (e.g. PAUSE on
x86).