Skip navigation
1 2 3 Previous Next

Vincent VAUBAN's Blog

203 posts


What's Reactive programming


Reactive programming has been used for an extremely long time.

Reactive programming brings four things together:

1) Elastic: ability to scale

2) Message-driven: no central database driving. "Don't expose your database, instead expose your data"

3) Responsive

4) Resilient (fail fast and gracefully)




RP is Data flow


Reactive programming is an improved kind of functional programming.

In FP, we do function composition  & lazy evaluation; and RP is built on top of these two concepts.

RP is dataflow computing say a stream of data.



Java 8 Streams vs Reactive Streams


  • Pipeline: in Java 8 Stream & in reactive streams too.

  • Lazy: Java 8 streams are lazy and reactive streams are lazy too.

  • Push of data: Java 8 is push of "data only", reactive stream is push of "data also". It means that while Java 8 Streams have only one channel: the data channel; Reactive streams have 3 channels: data/errors/completion. The data channel is in charge of getting data assuming there are no errors, the completion channel will eventually send a complete status complete which makes the data channel to close. An if there is an error the data channel close and you get the error.

  • Java 8 streams have only one pipeline, you can't fork it. Reactive streams can have multiple subscribers say it can fork.

  • Java 8 streams are in a "push at will" mode, while reactive streams are in a "backpressure" mode say it adapts to the subscribers.

  • In Java 8 streams, we speak of sequential vs parallel streams. While in reactive streams we speak about sync vs async streams.




There are many java reactive tools:




Reactive Streams API


Flowable.interval(1, 1, TimeUnit.SECONDS)

                .map(e -> e * 2)



  • Involved stakeholders: Eclipse foundation, Pivotal, Netflix, Lightbend...

  • Publisher: publishes/emits data (Flowable), it is a data source of potentially unbounded stream of data

  • Subscriber: subscibres/receives data (subscribe), it is a receiver of data from a publisher

  • Subscription:  kind of session with the publisher, so you can have multiple relationships (sessions) with the publisher if you want, it is like a session between a publisher and a subscriber

  • Processors: both publisher and subscribers (map/filter), it is the processing stage: acts as both publisher and subsriber





  • Backpressure it is when you have an observable which emits items so fast that consumer can't keep up with the flow leading to the existence of emitted but unconsumed items.

  • There are different backpressure strategies: BUFFER (keep all), DROP(keep the available), LATEST(keep the last)




Reactive Stream in Java SE


A standardization of reactive stream have been done near a decade after the first tools appearance.

It consists of the java.util.concurrent.Flow classes and its 4 inner interfaces: Publisher, Subscriber, Processor and Subscription.

It only defines the interfaces, you have to use the existing tools: RxJava, AKKA, Reactor... to build your application.

Major OpenJDK projects


=>JDK 14, JDK 15, JDK 16, ... --  features, APIs, performance, quality


=>value types, generic specialization


=>virtual threads (formerly "fibers")


=>native memory & functions, vectorization


=>productivity-oriented languages features


Amber features

*Local variable type inference ("var") --Java 10--

*Text blocks --preview in Java 14--

*Switch expressions --Java 14--

*Records --preview in Java 14--

*Sealed types --future--

*Pattern matching for instanceof --preview in Java 14--


Local variable type inference ("var")

*For declaring local variables only, can use car instead of type

=>this is still static typing -- the compiler infers the type

=>Java is not turning into JavaScript!

*Isn't one of Java's strengths that types are declared explicitly?

=>static typing is still a strength

=>sometimes a variable's type is unimportant in context

=>in such cases, explicit types sometimes add clutter


Example of local variable type inference ("var"): cluttered code

try (InputStream iStream = socket.getInputStream();

InputStreamReader isReader =

new InputStreamReader(iStream, csName);

BufferedReader bufReader = new BufferedReader(isReader))


     return bufReader.readLine();



Example of local variable type inference ("var"): clean code

try (var iStream = socket.getInputStream();

varr isReader = new InputStreamReader(iStream, csName);

var bufReader = new BufferedReader(isReader))


     return bufReader.readLine();



Text blocks

*A "two-dimensional" string literal

=>supports multiple lines without escape sequences and appending

=>newlines mormalized to \n for cross-platform repeatability

=>supports standard escape sequences, plus additional for newline and whitespace control

*"Smart" policy for removal of incidental whitespace

=>allows reindentation of code without affecting string contents

*New String APIs

=>formatted(), stripIndent(), translateEscapes()


Example of text block with syntactic noise

void writeHTML() {

     String html =

          "<html>\n" +

          "     <body>\n" +

          "          <p>Hello world!</p>\n" +

          "     </body>\n" +





Example of text block without syntactic noise

void writeHTML() {

     String html = """



                    <p>Hello world!</p>






*Concerning the new line conventions between Linux and Windows,

if you take this code from Linux to Windows.

The new line separator is simply the "NL" Character not the blind feed character as opposed to carriage return linefeed.

*Concerning the leading white spaces,

the string before the leftmost line is called the incidental white space, and it is stripped away.


Switch expressions

*Historically, switch is a statement

=>requires break in each case --easy to forget

=>sometimes want to do an assignment in each case --easy to forget

=>possible to omit a case, in which (silently) nothing happens

     #might not be what you want

*In these cases, intent can be expressed better with an expression

=>typically uses new label form -> to avoid the need for a break statement

=>note: -> is not a lambda expression

=>expression must be exhaustive

=>all values must be handled, or default case provided


Example of switch statement

int numletters;

switch (day) {

     case MONDAY:

     case FRIDAY:

     case SUNDAY:

          numletters = 6;


     case TUESDAY:

          numletters = 7;


     case THURSDAY:

     case SATURDAY:

          numletters = 9;


     case WEDNESDAY:

          numletters = 10;


     default: throw new UnexpectedDayException(day);



Example of switch expression

int numletters=

   switch (day) {

     case MONDAY, FRIDAY, SUNDAY-> 6;

     case TUESDAY-> 7;

     case THURSDAY, SATURDAY-> 9;

     case WEDNESDAY-> 10;


*Exhaustive -- no default clause needed, as all cases covered

*Exhaustiveness allows compiler to distinguish between "I want to handle all cases explicitly" from "I want to handle some cases but not others".



*A transparent, shallowly immutable data aggregate class

=>an aggregation of named fields

=>every fields has a correspondingly-named public accessor method

=>sort of like a nominal tuple

*A record is a class

=>equals(), hashCode(), toString() are provided and can be overridden

=>constructor can be overridden to perform argument validation

=>additional methods are allowed

=>can implement interfaces

=>API is entirely defined by state description (i.e, fields)

*Records are restricted class

*Cannot be subclassed

=>tremendously complicates semantics of equals()

=>avoids issues with accidental "decapitation" --when upcasting--

=>fields ("record component") form the complete state of a record

*Are shallowly immutable

=>all fields are implicitly final

=>can contain references to mutable objects

=>firmer foundation for later features, e.g. deconstruction (see later)


Example before use of Record

class point {

   final int x;

   final int y;


   public Point(int x, int y){

      this.x = x;

      this.y = y;




   public boolean equals(Object o) {

      if(this==o) return true;

      if(o == null ||

         getClass()!= o.getClass())

        return false;


      Point point = (Point) o;


      if(x!=point.x)return false;

      return y == point.y;




   public int hashCode() {

       int result = x;

       result = 31 * result + y;

       return result;




   public String toString(){

       return "Point{x="+x+", y="+y+"}";



   public int x() { return x; }


   public int =y() { return y; }




Example with use of Record

record Point(int x, int y) { }

*The constructor, equals(), hashCode(), toString(), and component accessors --x() & y()-- are all provided automatically.


record use case

List<Person> topNByScore(List<Person> list, int n){



   record PersonX(Person person, long score) {}




            .map(p -> new PersonX(p, computeScore(p)))






*A local record, like a local class. A class has too much syntactic overhead to use this way.


Sealed types

*Allows a class to control its subclasses

=>"final" is too restrictive -- prevents all subclassing even with library

=>workarouund is to provide only package-private constructor

=>inflexible: only works with classes, not interfaces

=>example: EnumSet subclasses RegularEnumSet and JumboEnumSet

*Sealed types

=>allows class or interface author to control subclasses/implementations

=>compiler and VM enforce well-defined set of subclasses/impls

=>explicitly using "permits" clause

=>or implicit to classes in the same file (including nested classes)


Example of sealed types

record Point(int x, int y) {}


sealed interface Shape

   permits Circle, Rect { }


record Circle(Point center, int radius)

   implements Shape { }


record Rect(Point lowerLeft, Point upperRight)

   implements Shape { }


Example of a variant of sealed types

record Point(int x, int y) {}


sealed interface Shape {

record Circle(Point center, int radius)

   implements Shape { }

record Rect(Point lowerLeft, Point upperRight)

   implements Shape { }


*"permits" clause inferred


Pattern matching for instanceof - before it

if(obj instanceof Integer) {

   int  intValue = ((Integer) obj).intValue();

   //use intValue


*type name repeated, obscur syntax. Most of the time there is a cast after instanceof


Pattern matching for instanceof

*Provide a binding variable name with instanceof

=>implicitly declares a new local variable

=>its type is the type name from instanceof

=>initialized by downcasting the reference to the instanceof type

*Use cases

=>probably gets rid of 90% of casts in existing code

=>quite useful in implementing equals()


Pattern matching for instanceof - now

if(obj instanceof Integer intObj) {

   //use intObj.intValue()


*there is a new local variable initialized by cast, whom scope is subsequent block


Pattern matching for instanceof - a more complicated example: old equals

public boolean equals(Object o){

   if(!(o instanceof ThisClass))

      return false;


      return true;

   ThisClass that = (ThisClass) o;

   return this.size == that.size &&




Pattern matching for instanceof - a more complicated example: new equals

public boolean equals(Object o){

   return (this==o) ||

      (o instanceof ThisClass that) &&

      this.size == that.size &&




Putting it all together

*Just a bunch of individual features, right?

=>switch expressions


=>sealed types

=>pattern matching for instanceof

*Features designed to work together

*Future enhancements in-progress:

=>add type patterns to switch expressions

=>with a sealed type, such a switch can enforce exhaustiveness

=>records allow deconstruction patterns


Putting it all together - Remember the previous sealed types

record Point(int x, int y) {}


sealed interface Shape

   permits Circle, Rect { }


record Circle(Point center, int radius)

   implements Shape { }


record Rect(Point lowerLeft, Point upperRight)

   implements Shape { }



Putting it all together - Application to switch: type pattern

//type pattern in switch

double area = switch (shape) {

   case Circle c -> areaOfCircle(c);

   case Rect r -> areaOfRect(r);


*no default case, since Shape is a sealed type with exactly two subtypes


Putting it all together - Application to switch: deconstruction pattern

//deconstruction pattern in switch

double area = switch (shape) {

   case Circle(var center, var radius) -> PI * radius * radius;

   case Rect (var p1, var p2) -> (p2.x-p1-x) * (p2.y-p1.y);



Putting it all together - Application to instanceof: deconstruction pattern

//deconstruction pattern in instanceof

if(shpe instanceof Circle(Point p,1)){

   // shape is a unit circle centered at point p



*1 is the value of the radius


Links of project Amber

*Project page - has links to all the JEPs


*See also Bierman & Goetz, Pattern Matching for Java


Define clauses


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.




A provides…with module directive specifies that a module provides a service implementation—making the module a service provider.

The provides part of the directive specifies an interface or abstract class listed in a module’s uses directive

and the with part of the directive specifies the name of the service provider class that implements the interface or extends the abstract class.



Define need

Not all modules on module graph.

When the JVM launches, the module system resolves dependencies and builds the module graph.

Only modules that make it into the graph are available at run time.

If modules are properly decoupled via services, there is a good chance, though, that the providing modules are not transitive dependencies of the initial module.

So without further efforts, service provider modules would routinely not make it into the module graph and thus not be available at run time when a module tries to use a service.



Additional modules on module graph thanks to "uses" and "provides...with" clause.

So for services to properly work, provider modules must make it into the module graph even if they are not transitively required from the initial module.

But how can the module system identify which modules are needed as service providers? All that use a provides clause? That would be a little too much.

No, only providers of services that are actually needed should be resolved.

This makes it necessary to identify services uses.

As others have pointed out, bytecode analysis is slow and unreliable, so a more explicit mechanism is needed to guarantee efficiency and correctness: uses clauses.

Only with them can the module system reliably and efficiently make all service provider modules available.


Java 14

Posted by vvauban Apr 12, 2020

Java 14 has been released last Tuesday (17 March 2020), the new features are:

―JEP 305: Pattern Matching for instanceof (Preview)

―JEP 343: Packaging Tool (Incubator)

―JEP 345: NUMA-Aware Memory Allocation for G1

―JEP 349: JFR Event Streaming

―JEP 352: Non-Volatile Mapped Byte Buffers

―JEP 358: Helpful NullPointerExceptions

―JEP 359: Records

―JEP 361: Switch Expressions (Standard)

―JEP 362: Deprecate the Solaris and SPARC Ports

―JEP 363: Remove the Concurrent Mark Sweep (CMS) Garbage Collector

―JEP 364-365: ZGC on macOS and Windows

―JEP 366: Deprecate the ParallelScavenge + SerialOld GC Combination

―JEP 367: Remove the Pack200 Tools and API

―JEP 368: Text Blocks (Second Preview)

―JEP 370: Foreign-Memory Access API (Incubator)

Here some details of some of them:

JAVA 14: JEP 305: Pattern Matching for instanceof (Preview)

Over the course of Project Amber, pattern matching for Java is being worked on. For the instanceof operator, pattern matching in Java 14 could become a reality, making the Java programming language more concise and secure. With pattern matching, the “form” of objects can be precisely defined, after which they are tested against their own input by statements and expressions.

The use of pattern matching in instanceof could lead to a strong decrease of necessary type conversions in Java applications. In future Java versions, pattern matching could be used for further language constructs such as switch expressions.

Writing equals() will get much nicer:



public boolean equals(Object o) {


  if (o == this) return true;





  if (!(o instanceof Money))


  return false;





  Money other = (Money)o;




  return this.amount == other.amount


  && Objects.equals(this.currencyCode, other.currencyCode);







public boolean equals(Object o) {



    if (o == this) return true;






    return (o instanceof Money other



            && this.amount == other.amount



            && Objects.equals(this.currencyCode, other.currencyCode));






JEP 343: Packaging Tool (Incubator), Create a tool for packaging self-contained Java applications.

With JDK 8, a tool called javapackager was released as part of the JavaFX kit. However, after JavaFX split from Java with the release of JDK 11, the popular javapackager was no longer available.

The packaging tool ensured that Java applications could be packaged in such a way that they could be installed like all other programs. For Windows users, for example, *.exe files could be created and their Java application installed by double-clicking. Since the tool is sorely missed, a new tool called jpackage is to pick up the mantle. Users can finally create their own Java installation files again, based on the Java application and a runtime image. The tool takes this input and creates an image of a Java application that contains all dependencies (formats: msi, exe, pkg in a dmg, app in a dmg, deb and rpm).

Commands to package non modular application:

$ jpackage --name myapp --input lib --main-jar main.jar  

Commands to package modular application:

$ jpackage --name myapp --module-path lib -m myapp  

It is installed by default in "C:/Program Files/".



JEP 345: NUMA-Aware Memory Allocation for G1

Multi-core processors are now the general standard.

In a NUMA( non-uniform memory access) memory architecture, each processor core receives a small amount of local memory, but the other cores are granted access to it.

JEP 345 plans to equip the G1 Garbage Collector with the possibility to use such architectures advantageously.

Among other things, this is intended to increase performance on very powerful machines.

JEP 345 serves exclusively for the implementation of NUMA support for the G1 garbage collector, only for memory management (memory allocation) and also only under Linux.

Whether this support of NUMA architectures also comes for other garbage collectors or for other parts such as task queue stealing is not known.

Concretely, G1's heap is organized as a collection of fixed-size regions.

If the +XX:+UseNUMA option is specified then, when the JVM is initialized, the regions will be evenly spread across the total number of available NUMA nodes.



JEP 349: JFR Event Streaming, Expose JDK Flight Recorder data for continuous monitoring


To consume the data today from JFR, a user must start a recording, stop it, dump the contents to disk and then parse the recording file.

This works well for application profiling, where typically at least a minute of data is being recorded at a time, but not for monitoring purposes.

With JEP 349, it is proposed to create an API, via which the data collected by the JFR can be used for the continuous monitoring of active and inactive applications.


//Prints the overall CPU usage and locks contended for more than 10 ms.



try (var rs = new RecordingStream()) {









     rs.onEvent("jdk.CPULoad", event -> {









rs.onEvent("jdk.JavaMonitorEnter", event -> {












JEP 359 Records for modeling data as data

JEP 359 brings records as preview feature for Java.

Records is a new type. It use the keyword 'record' as you would use the keyword 'class'.

It provides a compact syntax for declaring classes which are transparent holders for shallowly immutable data. It is a more restricted kind of class.

A record is “the state, the whole state and nothing but the state”.

It consists of a name, the status description and the body:

record Person (String firstName, String lastName) {



      static int x;









      public static void doX() {















      public String getFullName() {



            return firstName + " " + lastName;







Even if it is not the primary goal,'record' skims boilerplate code like accessors, equals(), hashCode(), toString().

Records remain classes, even if they are restricted.

For example, they can contain annotations or Javadocs,

and declare their bodies as static fields, methods, constructors, or instance methods.

What they cannot do, however, is extend other classes or declare instance fields.



JEP 361: Switch Expressions (Standard)

With JEP 325 (Switch Expressions), it was proposed to extend the switch statement so that it can be used either as a statement or as an expression.

Both forms should be able to use either “traditional” or “simplified” variables and control structures.

The aim of this JEP was to simplify daily programming and pave the way for Pattern Matching (JEP 305).

It changes the case notation.

In addition to the obvious arrow instead of the colon, several values can also be listed for testing purposes since Java 12.

No break is needed anymore.

With JEP 354 Gavin Bierman suggested to adapt the functionality a little bit.

To output a value from a switch expression, the value statement is to be replaced by a yield statement.

―Arrow labels

int numLetters = switch (day) {



     case MONDAY, FRIDAY, SUNDAY -> 6;



     case TUESDAY -> 7;



     case THURSDAY, SATURDAY -> 8;



     case WEDNESDAY -> 9;




―Yielding a result

int j = switch (day) {



     case MONDAY -> 0;



     case TUESDAY -> 1;



     default -> {



          int k = day.toString().length();



          int result = f(k);



          yield result;









JEP 362: Deprecate the Solaris and SPARC Ports

In computing, to port means to transfer (software) from one system or machine to another.

"the software can be ported to practically any platform"

So when saying "Deprecate the Solaris and SPARC Ports" means that Java will no more take charge of the Solaris/SPARC platform.

The effort to make Java run on such platforms will be granted to other new Java features.

The Solaris operating system is still a part of the Sun Microsystems inventory and is no longer really up to date. Accordingly, Oracle’s wish to mark the ports for Solaris/SPARC, Solaris/x64 and Linux/SPARC as deprecated is not surprising. The next step, according to JEP 362, is to get rid of them in a future update. However, it should be noted that old Java versions (up to JDK 14) should run unchanged on old systems, including the corresponding ports.

The goal of the whole thing is to be able to take care of other features. However, if there is a group of dedicated and interested developers who want to maintain and administer the ports, the removal from the JDK could be overturned at a later date.



Helpful NullPointerExceptions

Improve the usability of NullPointerExceptions generated by the JVM by describing precisely which variable was null.


Suppose an NPE occurs in this code:

a.i = 99;  

The JVM will print out the method, filename, and line number that caused the NPE:

Exception in thread "main" java.lang.NullPointerException



    at Prog.main(

Using the message, which is typically included in a bug report, the developer can locate a.i = 99; and infer that a must have been null.

However, for more complex code, it is impossible to decide which variable was null without using a debugger. Suppose an NPE occurs in this code:

a.b.c.i = 99;  

The filename and line number do not pinpoint exactly which variable was null. Was it a or b or c?


If the more complex statement a.b.c.i = 99; throws an NPE, the message would dissect the statement and pinpoint the cause by showing the full access path which led up to the null:

Exception in thread "main" java.lang.NullPointerException:



     Cannot read field "c" because "a.b" is null



     at Prog.main(

1. BaseStream.parallel()



BaseStream.parallel() returns an equivalent stream that is parallel.




IntStream range2 = IntStream.rangeClosed(1, 5);


2. Collection.parallelStream()


Collection.parallelStream() returns a possibly parallel Stream with this collection as its source.



public static void main(String[] args) {

List<String> alpha2 = getData();


private static List<String> getData() {

List<String> alpha = new ArrayList<>();

int n = 97; // 97 = a , 122 = z
while (n <= 122) {
char c = (char) n;

return alpha;

Outputs alphabet letters in random order.


javac -d outDir --module-source-path simple-modules $(find simple-modules -name "*.java"]


java --module-path outDir -m


Other commands:

module-path – We use the –module-path option to specify the module path. This is a list of one or more directories that contain your modules.
add-reads – Instead of relying on the module declaration file, we can use the command line equivalent of the requires directive; –add-reads.
add-exports – Command line replacement for the exports directive.
add-opens – Replace the open clause in the module declaration file.
add-modules – Adds the list of modules into the default set of modules
list-modules – Prints a list of all modules and their version strings
patch-module – Add or override classes in a modules
illegal-access=permit|warn|deny – Either relax strong encapsulation by showing a single global warning, shows every warning, or fails with errors. The default is permit.


Be aware of rownum

Posted by vvauban Jul 4, 2019
select * from emp where ROWNUM <= 5 order by sal desc;

The intention was most likely to get the five highest-paid people—a top- N query.

What the query will return is five random records (the first five the query happens to hit), sorted by salary.

by Alina Yurenko, Oracle


I Graal VM pros


Why GraalVM

  • Universal Virtual Machine

  • Efficient/Performant

  • Multilingual/Polyglot

  • Embeddable

  • Secure

  • Open source


Graal VM sits between languages and platforms



GraalVM architecture




GraalVM Compiler


  • Modern compiler, written from scratch

  • Integrates with the HotSpot JVM

  • Focus on high performance and extensibility

  • Optimized performance for a wide set of languages


Compiler interaction with VM



Demo: java performance



mvn clean install

java -jar -XX:USeJVMCICompiler target/benchmark.jar

java -jar target/benchmark.jar


So, on a simple jar performance benchmarking, it results that GraalVM compiler builds a jar which is twenty times faster than the standard hotspot compiler build jar.



Advanced optimizations are done by GraalVM


  • Inlining

  • Polymorphic inlining

  • Partial escape analysis (calculates if objects need to be allocated to the heap)

  • Path duplication

  • And many more



Compiling Scala faster with Graal VM






II Polyglot programs

Language implementation API


  • Run programming languages efficiently on GraalVM

  • Create language interpreters as Java programs using Truffle API

  • Get access to the rich tooling, provided by the GraalVM ecosystem



Polyglot capabilities


  • Run JavaScript, R, Python, or Ruby in the context of Java applications

  • Secure sandboxing mechanisms

  • Zero overhead interoperability

  • Work with one set of tools for all languages


Enable more language


$GRAAL_HOME/bi/gu install python

$GRAAL_HOME/bi/gu install r

$GRAAL_HOME/bi/gu install ruby



Demo: polyglot program



node --jvm --polyglot server.js


So, an application can run with different languages in the same js file: Java standard libraries, R methods, and JS.


III Native images




  • Instant startup, low footprint

  • Works with memory management

  • Secure execution

  • AOT-compiled using the Graal compiler


Native images are precompiled ahead of time




Native image generation


It takes all the classes needed from the JDK, then it is optimized, then it is put in the binary with a substrate VM (little implementation of VM.)



Demo: Native images



native-image ListDir

time java ListDir

time ./ListDir

So the native binary application is ten times quicker than the regular application due to the Ahead Of Time compilation.





IV Ecosystem


  • Spring Framework

  • Micronaut

  • Fn Project

  • Helidon


V Sum-up


  • Fast Java, Scala, Kotlin, Groovy, Clojure

  • Instant startup, low footprint

  • Polyglot & embeddable VM

  • Interoperability between node.js, Python, Ruby, R


Modular development with JDK9

Posted by vvauban May 30, 2019


by Alex Buckley, Java platform group, Oracle --Octobre 2017--




Part I: Programming in the large

Programs are classes


It seems that an application could be a single package containing a few very rich classes all sharing data and fields accessible within the package and where a handful of public classes form the entry points or the API of the application.



Programs do not consist of a handful of packages anymore.


Problem: The only way to share code between packages is with the public modifier but then you're sharing it with everyone.


So: A package is a great way to organize classes but most people wish there was a way to organize packages to modules.

Let's define a module: A module is a set of packages designed for reuse.

In conclusion: In JDK9, programs are modules.


Example: java.base module







In blue, are the packages that can be used outside of the module.

In red, are the packages that can be used only inside of the module.


The module is  declared in a file:


module java.base {

     exports java.lang;



     exports java.util;


  -->It gives the name of the module
  -->and its exported packages


So: A module is a set of exported packages and concealed packages.


Accessibility JDK1-JDK8 vs JDK9


      # public
      # protected
      # package
      # private


      # public to everyone
      # public but only to friend modules
      # public only within a module
     # protected
      # package
      # private

Access control is more powerful in JDK9 than JDK8


Take as an example an 'Hello world' module


  -->The class


// src/com/example/hello/
package com.example.hello;
import java.lang.*;
public class SayHello {
     public static void main(String[] args){
          System.out.println("Hello world");


  -->The module information


// src/
module {
     exports com.example.hello;


  -->The compilation command


javac -d classes -sourcepath src com/example/hello/


This module requires the java.lang package from the base module.


What if multiple modules export the imported package if we intends to reuse the Java base module we should specify it.


With? The 'requires' directive.


What happens if code uses concealed packages? Find another api which is not concealed.



  • module-info exports PACKAGES

  • but requires MODULES


because "The unit of reuse is the unit of release".


Ok, but how do you run a modules application?
java -p mods -m hello-world

  • -p mods specifies that modular jars are to be found in the mod directory

  • and -m HelloWorld specifies the module to run



Constraints at the modular application resolution:

  -->No missing dependencies
  -->No cyclic dependencies
  -->No split packages (no classes loading doubloons from different jars)


Friends modules

You can select a restricted list of jars with whom you will share a package by the following directive:

exports my.package to friend1, friend2;

This avoid 'my.package' to be overloaded by anyone else which would create undesirable dependency to 'my.package'.


Summary of part I: Programming in the large

  -->A module is a set of packages designed for reuse
  -->Modules offer strong encapsulation and reliable dependencies
  -->Module-aware tooling is a big part of modular development


Part II: Migrating to modules


There 3 kinds of code to consider:

  -->My application code
  -->The libraries code
  -->The JDK code


The JDK code is already modularized: java.base, java.logging, java.sql, and java.xml modules.
The librairies code migration to modules depends of the editors of these libs.
And the code of my application is up to me to modularize it.



  -->Modules of my application

       # Name: that's easy
       # What modules does it require?
       # What packages does it export?

To know the dependencies of your jars, use jdeps: it report to you which jars your jar depends of.


jdeps -s lib/myapp.jar

It is not necessary to put 'requires java.base' because it is put for you by the compiler.

So, how do you specify in modules that do not exist yet?Use automatic modules.


Automatic modules

  -->"Real" modules
  -->No changes to someone else's JAR file
  -->Module name derived from JAR file name (Hyphens to dots, no version)
  -->Exports all its packages
  -->Requires all other modules


Summary of part II: Migration to modules

  -->Each application JAR is usually a good candidate to be a module
  -->Each library JAR will modularize at its own pace
  -->Automatic modules mean you're not waiting for the weakest link


Part III: The modular JDK

The JDK is huge ten of thousands of class.

In fact, the JDK is an aggregation of frameworks (swing, crypto, xml...)

This resulting coupling of frameworks has collateral effects: development and testing costs, difficulty to secure the whole, memory footprint.

So it has been broken on modules:

This accomplishment will prevent any recreation of monolith.

Java EE modules are deprecated for removal:

  • java.activation

  • java.corba

  • java.transaction

  • java.xml.bind




Illegal access to JDK internals causes runtime warnings.

Changes unrelated to modules:

  • Maven

  • Eclipse

  • Spring ElasticSearch

  • JUnit

  • Gradle

  • IntelliJ

  • Hibernate

  • Hadoop

  • ASM


Summary of part III: The modular JDK

  -->Modules all the way down
  -->JDK internals are accessible temporarily in JDK9
  -->You may need to upgrade tools and librairies to their JDK9-aware versions


Summary of summaries

  -->A module is a set of packages designed for reuse
  -->Automatic modules assist with migration to modules
  -->You may need to upgrade tools and librairies to their JDK9-aware versions



JAVA SE 11 new features

Posted by vvauban May 19, 2019

by Aurelio Garcia Ribeyro (Director of Product Management, Java SE --Oracle--), Nick Ristuccia (Senior Curriculum Developer, Oracle), Mikael Vidstedt (Software development director, Oracle), Glenn Maslen (Senior Manager, Curriculum Product Management, Oracle)

1) Release cadence overview

Previous JDK release model was two year based
New JDK release model is 6 months based for feature releases
New JDK release model offer Long Term Support (LTS) releases say releases with a wide range of year supports (contrary of the 6 months feature release support)
These LTS will occured every three years
Oracle JDK and Open JDK will be interchangeable from Java 11
Licensing between Oracle JDK and Open JDK differs: Open JDK is GPL (free) licensed while Oracle JDK is commercial licensed.
The cost of Oracle JDK license is due to the support going with it.



2) Making Java more Open

What was recently been open-sourced:

*Application class data sharing (OpenJDK 10)

  -->Enables you to place classes from the standard extensions directories and the application class path in the shared archive

*Project ZGC (OpenJDK 11)

  -->Low latency garbage collector to suport multi-terabytes heaps

*Flight recorder (OpenJDK 11)

  -->Collects diagnostic and profiling data about a running Java application

*Mission Control (JMC Project in OpenJDK)

  -->Monitor and manage Java applications with minimal performance overhead

*Usage logger

  -->Locally reports how Java is being used in your system


3) New in Java SE 11

17 JEPs


*JEP 330: Launching single source file programs

  -->Simplify the 'on ra;p' for new Java users

    Before: $Javac -d classes
             $Java -cp classes HelloWorld
     After:  $java

     class HelloWorld {
          public static void main(String... args){


*JEP 321: HTTP Client
HTTP client that implements HTTP/2 and WebSocket

  -->Standardizes the incubated HTTP client API in the package
  -->It supports

        # HTTP/1.1 and HTTP/2
        # both synchronous and asynchronous programming models
        # handles request and response bodies as reactive-streams, and
        # follows the familiar builder pattern


*JEP 332: Transport Layer Security (TLS) 1.3

  -->TLS 1.3 is a major overhaul of the TLS protocol and provides significant security and performance improvements over previous versions
  -->TLS 1.3 is a new version which supersedes and obsoletes previous versions of TLS including version 1.2 (RFC 5246)
  -->It also obsoletes or changes other TLS features such as the OCSP stapling extensions (RFC 6066, RFC 6961), and the session hash and extended master secret extension (RFC 7627)
  -->Deliver new cryptographic algorithm support for the following optional TLS 1.3 features

        # ChaCha20/Poly1305 cipher suites (8140466)
        # X25519/X448 elliptic curve algorithms (8171279)
        # edDSA signature algorithms (8166596)


*JEP 328: Java Flight Recorder
Profiling with extremely low overhead

  -->Enabled with -XX:StartFlightRecording option
  -->Built deep inside the JVM & JDK, by the engineers developing the JVM/JDK
  -->Always on -less that 1% overhead in production deployment
  -->High performance flight recording engine and data collection for Enterprise mission-critical workload

        # Access to data already collected in the JVM runtime
        # Thread local native buffers
        # Invariant TSC for time stamping
        # More accurate method profiling (method profiling data even from outside safe-points)
        # Faster and more accurate allocation profiling with automatic memory leak detection


*JEP 333: ZGC - Predictable, low latency, large heap GC

  -->Multi-terabyte heaps
  -->10ms Max GC pause time
  --> Lay the foundation for future GC features
  -->15% Max application throughput reduction






*JEP 286: Local-Variable type inference (JDK10)

  -->Previously, all local variable declarations required an explicit type on the left-hand side

  ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

  -->Now, the explicit type can be replaced by the reserved type name var
  -->The compiler infers the variable type from the initializer on the right-hand side

  var outputStream = new ByteArrayOutputStream();


*JEP 286: Example of benefits

  -->Code to read a line of text from a socket using try-with-resources:

  try(InputStream is = socket.getInputSTream();
      InputStreamReader isr = new InputStreamReader(is, charsetName);
      BufferedReader buf = new BufferedReader(isr)) {
     return buf.readLine();

  -->With local-variable type inference:

  try(var inputStream = socket.getInputStream();
      var reader = new InputStreamReader(inputStream, charsetName);
      var bufReader = new BufferedReader(reader)){
      return bufReader.readLine();

      # Variable names align (more readable)
      # Class names aren't repeated (more concise)


*JEP 286: Reserved Type Name var

  -->Keywords cannot be used for variable names

     int else - 10;   //Not valid

  -->var is not a keyword

     int var = 20; //Valid, but not recommended
                   //Old code like this won't break under Java 11

  -->var for type inference is only used when we know we're looking for type information

      var x =30;


*JEP 286: Where can it be used?

  -->Local variables with initial value

     var itemDescritpion = "Shirt";  //inferred as String

   -->Enhanced for-loop indexes

      for(var item : itemArray)     //inferred as Item object

  -->Traditional for-loop index variables

    for(var i=0;i<10;i++)   //inferred as int

  -->Some non-denotable types:

       # Intersection types
       # Anononymous class types


*JEP 286: Where can it not be used?

  -->Declarations without an initial value

     var price;

  -->Initialization with a null value

     var price = null;

  -->Compound declarations

     var price=9.95, tax=0.05;

  -->Array Initializers

     var prices = {9.95, 5, 3.50};


     public var price;


     public void setPrice(var price){…}

  -->Method return type

     public var getPrice(){
         return price;


*JEP 286: Why not?

  -->Consider this bad-example method:

     public var getSomething(var something){  //How should this compile?
           return something;  //something could be anything

  -->Type inference is an algorithm, not magic

      # A goal of this feature is to let developers more-quickly read and understand code
      # Both humans and the compiler require context for understanding

  -->Prevent "action at a distance" issues

      # Don't allowcode elsewhere to conflict on what type to infer--This prevents binary incompatibilities--
      # Type must be inferred where the variable is declared


*JEP 286: The debate

  -->Arguments against this feature:

       # "Useful information will be hidden"
       # "Readibility will be impaired"
       # "Bad developers will misuse and overuse the feature to write terrible code"

  -->Arguments for this feature:

       # "Redundant information is removed"
       # "Code is more concise and readable"
       # "Bad developers will write terrible code no matter what"

  -->Like all features, it must be used with judgment
  -->Follow these guidelines to more effectively realize the benefits:


*JEP 286: Guideline 1

Choose a variable name thatt provides useful information

  -->Consider names that express the variable's role or nature:

    try(Stream<Customer> result = dbconn.executeQuery(query)){
     try(var customers= dbconn.executeQuery(query)){

  -->Consider names that convey the variable's meaning or type:

     List<Customer> x = dbconn.executeQuery(query);
     var custList = dbconn.executeQuery(query);


*JEP 286: Guideline 2
Miniimize the scope of local variables

     var items = new ArrayList<Item>(...);
     for(var item: items) ...

  -->Imagine, we change it by a set, knowing that a set does not have iterator order (so MUST_BE_PROCESSED_LAST is no sure to be processed last). And that the scope of the variable is extended by hundred of line of codes between the initial instructions:

     var items = new HashSet<Iten>(...);
     // ... 100 lines of code ...
     // ... 100 lines of code ...
     // ... 100 lines of code ...
     // ... 100 lines of code ...
     // ... 100 lines of code ...
     for(var item: items) ...

  -->The result is that, it leads to a bug so shorten the scope


*JEP 286: Guideline 3
Consider var when the initializer provides sufficient information

  -->Here both sides of these statements offer type information:

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
     BufferedReader reader = Files.newBufferedReader(...);
     List<String> list = List.of("a","b","c");  //Before

  -->Constructor or factory method calls are enough context:

     var outputStream = new ByteArrayOutputStream();
     var reader = Files.newBufferedReader(...);
     var list = List.of("a","b","c");  //After


*JEP 286: Guideline 4
Consider var to split chained or nested expressions

  -->These examples take a collection of Strings and find which occurs most
  -->As a single expression, it's hard to decipher the stream and optional mix:

     return     //before
              .collect(groupingBy(s->s, counting()))

  -->Splitting it may yield a good balance of readibility and concision:

     var freqMap =    //After
     var maxEntryOpt = freqMap.entrySet()


*JEP 286: Guideline 5
Don't worry too much about "Programming to the interface" with local variables

  -->A common Java idiom is to construct an instance with a concrete initializer type, but assign it to a variable of an interface type

      List<string> list = new ArrayList<String>();
                        = new CopyOnWriteArrayList<String>();
                        = new LinkedList<String>();

  -->This isn't possible with local variable type inference

      var list = new ArrayList<String>();


*JEP 286: Guideline 6
Take care using var with diamond or generic methods

  -->Consider this statement:     

       PriorityQueue<Item> itemQueue = new PriorityQueue<Item>();

  -->The "diamond" feature lets you omit explicit type information:

       PriorityQueue<Item> itemQueue = new PriorityQueue<>();

  -->var also lets you omit explicit type information:

       var itemQueue = new PriorityQueue<Item>();

  -->Using both strips the statement of context:

       var itemQueue = new PriorityQueue<>();  //Inferred as
                                               //which may not be helpful

  -->Arguments can provide context so type is inferred properly:

      Comparator<String> comp = ...;             //Inferred as
      var itemQueue = new PriorityQueue<>(comp); //PriorityQueue<String>


*JEP 286: Guideline 7
Take care using var with literals

  -->There is no issue with boolean, character, long, and String literals:

     //Before                    //After
     boolean ready = true;       var ready = true;
     char ch='\ufffd';           var ch = '\ufffd';
     long sum = 0L;              var sum = 0L;
     Strng label = "wombat";     var label = "wombat";

  -->Whole numbers require care, as they may be inferred as integer types:

     byte flags = 0:              var flags=0;
     short mask = 0x7fff;         var mask = 0x7fff;
     long base=17;                var base = 17;

  -->Floating point numbers require a little care, if you previously mixed types:

      float f1 = 1.0f;             var f1 = 1.0f;
      float f2 = 2.0;              var f2 = 2.0; //inferred as double
      double d3 =3.0;              var d3 =3.0;
      double d4 = 4.0f;            var d4 = 4.0f; //inferred as float


*JEP 323: Local-variable syntax for lambda parameters

  -->Lambda expressions could be explicitly typed:

     (Item x, int y) -> x.process(y)

  -->Lambda expressions could be implicitly typed:

     (x,y) -> x.process(y)

  -->Now, lambda expressions can also be implicitly typed with the var syntax:

     (var x, var y) -> x.process(y)


*JEP 323: Benefits

  -->Uniform syntax for local-variables type inferences:

     var x = new BigClassNamesMakeReadingHard();
     (var x, var y) -> x.process(y)

  -->Previously, annotations and modifiers required explicitly typed lambdas:

      (@Nonnull BigClassNamesMakeReadingHard x, final int y) -> x.process(y)

  -->var provides the more-readable implicitly typed alternative:

       (@Nonnull var x, final var y) -> x.process(y)


*JEP 323: these won't compile

  -->You could never mix implicitly and explicitly typed lambda parameters:

    (Item x, y) -> x.process(y)

  -->You cannot mix var and non-var in implicitly typed lambda expressions:

     (var x, y) -> x.process(y)

  -->You cannot mix var and non-var in explicitly typed lambda expressions:

     (var x, int y) -> x.process(y)

  -->You cannot omit parenthesis for single explicitly typed or var parameters:

     Item x -> x.toString();
     var x -> x.toString();

4) Beyond Java 11


*The next big opportunitues after Java 11

  -->Data optimization
  -->HW acceleration
  -->Continual language enhancements


*Specific projects on



*Project Valhalla

The data layout we have now



The data layout we want




*Project Loom

  -->Easier and more scalable concurrency model

      # making blocking calls virtually free

  -->"Fibers" (lightweight threads) and continuations

      # Millions of fibers can be spawned in a singe JVM instance


*Project Amber

  -->Language improvements

      # Dynamic Class-File Constants
      # Raw string literals
      # Switch expressions (preview in the JDK12)
      # Pattern matching


*Project Panama

  -->Foreign functions & data
  -->Simple, safe, and performant replacement for JNI
  -->Access to low-level hardware functionality through normal Java code

      # Vector instructions, special memory types (for example non-volatile memory)

  -->Big data, Machine Learning


*Project Skara

  -->Proposes to investigate alternative SCM and code review options for the JDK source code
  -->Options being investigated include those based upon Git rather than Mercurial
  -->Goal is to help OpenJDK contributors to be more productive, both seasoned committers and relative newcomers


*In a world of containers, we expect

  -->Safety and security becoming increasingly more important

       # Many instances
       # Mix of different applications
       # Heterogeneous machines
       # Heterogeneous container configurations


*Java in a world of containers
Java's characteristics make it ideal for a container environment

  -->Managed language/runtime
  -->Hardware and operating system agnostic
  -->Safety and security enforced by JVM
  -->Reliable: Compatibility is a key design goal
  -->Runtime adaptive: JVM ensures stable execution when environment changes
  -->Rich eco system
  -->We are committed to keeping Java the first choice for container deployments


*Container awareness

  -->JDK-8146115: Docker container detection and resource configuration usage (jdk8, jdk10+)
  -->JDK-8186248: More flexible, percentage based heap sizing flags (jdk10+)
  -->JDK-8179498: Namespace aware attach (jdk10+)
  -->JDK-8193710: Docker container aware jcmd (jdk11+)
  -->JDK-8203357: JDK internal container metrics API (jdk11+)
  -->... and more to come!

also view Matthew Gilliard's blog:


*Java & container




*Alpine Linux & musl libc

Small. Simple. Secure.

  -->Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox. (
  -->musl is lightweight, fast, simple, free, and strives to be correct in the sense of standards-conformance and safety ( )


*Project "Portola" - Alpine Linux/musl

  -->OpneJDK project "Portola" provides a port of the JDK to Alpine/musl
  -->The Alpine Linux base image weighs in at 4MB

       # Uses the "musl" C library





5) Training

  -->A choice of live and self-paced Java training titles
  -->Obtainable as:

      # Individual titles and exams
      # Learning subscription containing groups of online coursed with certification access

  -->Training for new Java programmers starting on Java 11
  -->Training for programmers moving up from JDK 8
  -->Titles available by February 2019



  -->Upgrading from Java 8 to Java 11: Exam 1Z0-817
  -->Java Novice (starting on Java 11): Exams: 1Z0-815 & 1Z0-816




6) Summary

  -->The Java platform development on OpenJDK is becoming more open
  -->JDK  11, the next LTS release, includes innovations, security, productivity and performance improvements
  -->Oracle is simplifying Java licensing by transitioning out of the BCL "dual purpose" license
  -->Oracle University offers courses and learning subscriptions - including Java 11 - for new and upgrading Java programmers
  -->Beyond Java 11, we have a solid technical roadmap


Function<T,R> represents a function that accepts one argument and produces a result.

Where T is the type of the input to the function and R is the type of the result of the function.

There is a specialization of Function for the case where the operand T and result R are of the same type: UnaryOperator<T>

public interface UnaryOperator<T> extends Function<T,T> represents an operation on a single operand that produces a result of the same type as its operand.

UnaryOperator<Integer> doubleIt = x->x*2;

int y = doubleIt.apply(2);



public final void join(long millis) throws InterruptedException

Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.

This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked.


In other way

The join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing,


causes the current thread to pause execution until t's thread terminates. Overloads of join allow the programmer to specify a waiting period. However, as with sleep, join is dependent on the OS for timing, so you should not assume that join will wait exactly as long as you specify.

Like sleep, join responds to an interrupt by exiting with an InterruptedException.



public static Set<String> getAvailableZoneIds() gets the set of available zone IDs.

This set includes the string form of all available region-based IDs. Offset-based zone IDs are not included in the returned set. The ID can be passed to of(String) to create a ZoneId.


LocalDateTime dt =;

List<String> zoneList = new ArrayList<>(ZoneId.getAvailableZoneIds());

for (String zoneId : zoneList) {

     ZoneId zone = ZoneId.of(zoneId);

     ZonedDateTime zdt = dt.atZone(zone);

     ZoneOffset zos = zdt.getOffset();

     // replace Z to +00:00

     String offset = zos.getId().replaceAll("Z", "+00:00");

     String out = String.format("%35s (UTC%s) %n", zoneId.toString(),offset);

     System.out.printf(out);//prints the zone ids and their offset, ex: America/Cuiaba (UTC-03:00)



default Predicate<T> and(Predicate<? super T> other)

Returns a composed predicate that represents a short-circuiting logical AND of this predicate and another. When evaluating the composed predicate, if this predicate is false, then the other predicate is not evaluated.


Predicate<String> widthLessThan20 = s->s.length()<20;

Predicate<String> containAVowel = s-> s.contains("a");

System.out.println("Less than 20 characters and containing the 'a' letter:");

System.out.println(widthLessThan20.and(containAVowel).test("Oracle community"));//true


You can reference a constructor by using the name new.

The functional interface Supplier contains one method get that takes no arguments and returns an object. Consequently, you can invoke a method with  a constructor reference as follows:

Supplier<List<String>> s =ArrayList<String>::new;

List<String> l = s.get();

So be sure the class invoking new by reference syntax contains a no-arg constructor.