Java Next!

New Releases, Amber, Valhalla, and More Goodies

Lots to talk about!

Versions and Features
The New World
Projects To Look Out For

Versions and features

Versions and Features
The New World
Projects To Look Out For

From Java 8 to Java 11.

Java 8

  • released 03/2014

  • free support ends 01/2019

What’s the core of 8?

  • n -> lambdas()
    Method::references

  • features.stream()

  • default method() { …​ }

Project Lambda

Project Lambda

  • launched with a straw-man (12/2009):

    #(int x, int y)(x * y)
  • 1st early draft review (11/2011):

    Callable<String> c = () -> "done";
  • 2nd review (06/2012) and 3rd review (01/2013)

  • public review (12/2013) and final ballot (02/2014)

Projects…​

  • start with an idea
    that is then evolved

  • can take a long time

  • are fairly open

Java 9

  • released 09/2017

  • free support ended 01/2018

What’s the core of 9?

Java Module System

Delaying Java since 2008!

JAR Hell is bad, mkay?

JARs have:

  • no name the JVM cares about

  • no explicit dependencies

  • no well-defined API

  • no concept of versions

Some consequences:

  • NoClassDefFoundError

  • no encapsulation across JARs

  • version conflicts

Modules

Modules are like JARs but have:

  • proper names

  • explicit dependencies

  • a well-defined API

  • no concept of versions 😭

Important goals:

  • reliable configuration

  • strong encapsulation

Module Declaration

A file module-info.java:

module java.sql {
	requires transitive java.logging
	requires transitive java.xml
	uses java.sql.Driver
	exports java.sql
	exports javax.sql
	exports javax.transaction.xa
}

Reliable Configuration

module java.sql {
	requires transitive java.logging
	requires transitive java.xml
}

Module system enforces:

  • all required modules are present

  • no ambiguity

  • no static dependency cycles

  • no split packages

Strong Encapsulation

module java.sql {
	exports java.sql
	exports javax.sql
	exports javax.transaction.xa
}

Say you want to access java.sql.ResultSet.

Module system only grants access if:

  • ResultSet is public

  • java.sql is exported by java.sql

  • your module reads java.sql

Feature Glance

Let’s look at two nifty features:

  • services

  • jlink

Services

The module system as a service registry:

module java.sql {
	uses java.sql.Driver
}

module mysql.driver {
	provides java.sql.Driver
		with com.mysql.MySQLDriver;
}

Loading Services

Code in java.sql can do this:

List<Driver> drivers = new ArrayList<>();
ServiceLoader
	.load(Driver.class)
	.forEach(drivers::add);

Application Image

# create image
$ jlink
	--output awesome-app
	--module-path $JAVA_HOME/jmods:mods
	--add-modules com.awesome.app
	--launcher awesome=com.awesome.app
# [ship image]
# use image
awesome-app/bin/awesome

More JPMS Features

  • finer grained dependencies and exports

  • open packages and modules (for reflection)

  • unnamed and automatic modules (for migration)

  • layers (for containers)

More About JPMS

Even More About JPMS

37% off with
code fccparlog

I’ve written a book!
E-book available ⇝ tiny.cc/jms

  • creating, building,
    running modules

  • migration to Java 9+

  • modularization

  • services and
    advanced features

  • reflection and layers

  • custom runtime images

Project Jigsaw

Project Jigsaw

Sun’s primary goal in the upcoming JDK 7 release will be to modularize the JDK […​], which we hope to deliver early in 2010.

😊

Jigsaw history

  • Oracle acquires Sun, Jigsaw is halted (2010)

  • Jigsaw starts exploratory phase (2011)

  • releases of Java 7 (2011) and Java 8 (2014)

  • exploratory phase ends with JSR 376 (2014)

  • a prototype is released (09/2015)

Java 9 history

  • Java 9 release was planned for 09/2016

  • Jigsaw delays it to 03/2017,
    then 07/2017, then 09/2017

  • public review ballot (05/2017)

Jigsaw history

  • public review ballot fails (05/2017)

  • various fundamental changes requested;
    only change: encapsulation turned off

  • reconsideration ballot passes (06/2017)

¯\_(ツ)_/¯

Projects…​

  • can lead to very heated discussions

  • are subject to politics

  • take feedback into account and
    adapt to new requirements

  • are not as open as they could be

  • can take a very long time and
    delay Java releases

Java 10

  • released 03/2018

  • free support ends 07/2018

What’s the core of 10?

Local-Variable Type Inference

Less typing, but still strongly typed

Type Duplication

We’re used to duplicating
type information:

URL codefx = new URL("http://codefx.org");
URLConnection connection = codefx.openConnection();
Reader reader = new BufferedReader(
	new InputStreamReader(
		connection.getInputStream()));

Not so bad?

Type Duplication

What about this?

No no = new No();
AmountIncrease<BigDecimal> more =
	new BigDecimalAmountIncrease();
HorizontalConnection<LinePosition, LinePosition>
	jumping =
		new HorizontalLinePositionConnection();
Variable variable = new Constant(5);
List<String> names = List.of("Max", "Maria");

Type Deduplication

Can’t somebody else do that?
Compiler knows the types!

Enter var:

var codefx = new URL("http://codefx.org");
var connection = codefx.openConnection();
var reader = new BufferedReader(
	new InputStreamReader(
		connection.getInputStream()));

Rules of var

var only works in limited scopes:

  • compiler infers type from right-hand side
    ⇝ rhs has to exist and define a type

  • only works for local variables, for, try
    ⇝ no var on fields or in method signatures

  • also on lambda parameters ⑪
    ⇝ annotate inferred type on lambda parameters

Rules of var

Two more:

  • not a keyword, but a reserved type name
    ⇝ variables/fields can be named var

  • compiler writes type into bytecode
    ⇝ no run-time component

What About Readability?

This is about readability!

  • less redundancy

  • more intermediate variables

  • more focus on variable names

  • aligned variable names

Aligned Variable Names

var no = new No();
var more = new BigDecimalAmountIncrease();
var jumping = new HorizontalLinePositionConnection();
var variable = new Constant(5);
var names = List.of("Max", "Maria");

What About Readability?

Still think omitting types is always bad?

Ever wrote a lambda without declaring types?

rhetoricalQuestion.answer(yes -> "see my point?");

More on var

Project Amber

More on that later!

Java 11

  • release 09/2018

  • free support ends 01/2019
    (yes, no free LTS—​more on that later)

What’s the core of 11?

Err…​

  • single-file source-code programs:

    java HelloWorld.java
  • reactive HTTP/2 client
    http://tiny.cc/http-2

  • Epsilon GC

Scripting Java

Faster feedback with fewer tools

Launching A Single Source File

Compiling and running
simple Java programs is verbose.

Not any more!

java HelloJava11.java

Background

How it works:

  • compiles source into memory

  • runs from there

Details:

  • requires module jdk.compiler

  • processes options like class/module path et al.

  • interprets @files for easier option management

Use Cases

Mostly similar to jshell:

  • easier demonstrations

  • more portable examples

  • experimentation with new language features
    (combine with --enable-preview)

But also: script files!

Scripts

Steps towards easier scripting:

  • arbitrary file names

  • shebang support

Arbitrary File Names

Use --source if file doesn’t end in .java:

java --source 11 hello-java-11

Shebang Support

To create "proper scripts":

  • include shebang in source:

    #!/opt/jdk-11/bin/java --source 11
  • name script and make it executable

  • execute it as any other script:

    # from current directory:
    ./hello-java-11
    # from PATH:
    hello-java-11

Isn’t that awesome?

Java 11

  • no language changes

  • no monumental dev-facing features

  • this will become common

  • that’s not a bad thing!

The new world

Versions and Features
The New World
Projects To Look Out For

Old release cadence

The plan

  • releases are driven by flagship features

  • new major release roughly every 2 years

Old release cadence

The reality

  • Java 7 took 5 years

  • Java 8 took 3 years

  • Java 9 took 3.5 years

"Bump an 'almost ready' feature
2+ years into the future?"

⇝ "Better to delay the release."

Downsides

  • implemented features provide no value

  • increases reaction time

  • puts (political) pressure on projects

  • makes everybody grumpy

The new world

If it hurts, do it more often.

  • fixed six-month release cadence
    (March and September)

  • ship everything that is ready

All are major releases
with known quality guarantees.

⇝ No "beta versions"!

Implementation

  • features are developed in "branches"

  • merged into "master" when (nearly) finished

  • "release branch" created 3 months prior

  • only bug fixes merged to "release branch"

Upsides

  • completed features get out earlier

  • no pressure to complete features on time

  • easier to incubate features

  • easier to react to changes in the ecosystem

Release fatigue?

"Java will change too fast."

"Constant migrations will be expensive."

"Test matrix will explode."

"Ecosystem will fragment."

Fast Change

The rate of innovation doesn’t change. The rate of innovation delivery increases.

— Mark Reinhold

Maybe speed will pick up a little:

  • recent activities target low-hanging fruits

  • Oracle is focusing on Java core (my impression!)

Fast Change

By and large:

Evolution will be steadier, not faster.

(see Java 11)

Expensive migrations

But not the norm:

  • Java 10 is trivial

  • Java 11 is easy

Oracle is still committed
to backwards compatibility!

Expensive migrations

Balance shifted between
compatibility vs evolution:

  • @Deprecated(forRemoval=true)

  • "one major release" is now 6 months, not 36

  • increasing bytecode level

  • incubating features (if used incorrectly)

Expensive migrations

Remedies:

  • stick to supported APIs

  • stick to standardized behavior

  • stick to well-maintained projects

  • keep dependencies and tools up to date

  • consider using jlink

Exploding test matrix

As the range of supported versions increases…​

  • builds need to run against all of them

  • developers need to switch between them

Many tools already support this.
⇝ We need to know how.

Also: Moar automization!

Fragmenting Ecosystem

"This will be like Python 2/3!"

No.

Advice

  • find a suitable update cadence

  • build on each release (including EA)

  • report problems

  • only rely on standardized behavior

  • heed deprecation warnings (jdeprscan)

  • keep dependencies and tools up to date

Most importantly:
Be aware of what’s coming!

Be aware

Don’t focus on versions!

Focus on projects and JEPs:

  • large features are developed by projects

  • smaller features are proposed by JEP only

Let’s have a look at what’s coming!

Long-term support

What if you (or your customers)
don’t want to update every six months?

Oracle JDK vs OpenJDK

Sun/Oracle JDK used to…​

  • contain more features

  • be perceived as more stable

  • be perceived as more performant

As of Java 11, on a technical basis,
Oracle JDK and OpenJDK are identical. *

Oracle JDK vs OpenJDK

Only difference is license and support model:

  • Oracle ships OpenJDK at jdk.java.net,
    licensed under GPL+CE

  • Oracle JDK is fully commercial:
    from 11 on, no free use in production

⇝ OpenJDK is the new normal!

Oracle support

What does Oracle support?

  • free updates for current OpenJDK version
    (i.e. six months)

  • commercial support for Oracle JDK
    for 5+ years for Java 11, 17, 23, etc.
    (called Java SE Subscription; prices)

⇝ No free LTS by Oracle.

Oracle support

How does Oracle handle bug/security/etc fixes?

  • usually developed on "master" (OpenJDK)

  • merged to current version’s "branch" (OpenJDK)

  • merged to current LTS version (Oracle JDK)

⇝ "LTS" means merging fixes
into old JDK versions.

Commercial LTS

Free LTS

Current discussions give hope:

  • free LTS for OpenJDK 11, 17, 23, etc.
    by the community for 4+ years

  • built and shipped by Adopt OpenJDK

Free LTS

[L]et me assure you of one thing: whether by Oracle or Red Hat or someone else, JDK LTS releases will continue to be supported. We all have a lot invested in Java, and we won’t let it fall.

— Andrew Haley, Red Hat (link)

Projects

Versions and Features
The New World
Projects To Look Out For

Many great features on the horizon!

Be aware

Don’t focus on versions!

Focus on projects and JEPs:

  • large features are developed by projects

  • smaller features are proposed by JEP only

Let’s have a look at what’s coming!

(Straw-man syntax ahead!)

Many great projects

  • Amber: smaller, productivity-oriented features

  • Valhalla: generic specialization and value types

  • Loom: fibers and continuations

  • Metropolis: Graal and ahead-of-time compilation

  • Panama: improved interaction with non-Java code

Project Amber

Smaller, productivity-oriented Java language features

Profile:

Already delivered var in Java 10!

Motivation

Java compared to more modern languages:

  • can be cumbersome

  • lacks expressiveness

  • tends to require boilerplate

Amber wants to improve that situation!

Endeavors

Raw string literals

String html =
	`<html>
		<body>
			<p>"Hello, string literals!"</p>
		</body>
	</html>`;

Yeah:

  • multiline strings

  • no escaping of special characters

Switch expressions

DayOfWeek day = // ...
int numLetters = switch (day) {
	case MONDAY, FRIDAY, SUNDAY -> 6;
	case TUESDAY -> 7;
	case THURSDAY, SATURDAY -> 8;
	case WEDNESDAY -> 9;
};

Yeah:

  • switch "gets a value"

  • no more break!

  • compiler checks exhaustiveness

Switch expressions

Pattern matching

Object value = // ...
String formatted = switch (value) {
	case Integer i -> String.format("int %d", i);
	case Byte b    -> String.format("byte %d", b);
	case Long l    -> String.format("long %d", l);
	case Double d  -> String.format("double %f", d);
	case String s  -> String.format("String %s", s);
	default        -> "unknown " + value.toString();
};

Yeah:

  • more powerful conditions

  • no repetition between condition and block

Pattern matching

Node n = // ...
int result = switch(n) {
	case IntNode(int i) -> i;
	case NegNode(Node n) -> -eval(n);
	case AddNode(Node left, Node right) ->
		eval(left) + eval(right);
	default -> throw new IllegalStateException(n);
};

Yeah:

  • deconstructing complex objects

  • goodbye visitor pattern!

Records

public record Range(int low, int high) {

	// compiler generates:
	//  * constructor, deconstructor
	//  * equals/hashCode/toString
	//  * accessors low(), high()

}

Yeah:

  • no boilerplate for plain "data carriers"

  • no room for error in equals/hashCode

  • makes Java more expressive

Records

The API for a record models the state, the whole state, and nothing but the state.

The deal:

  • give up encapsulation

  • couple API to internal state

  • get API for free

Customized records

public record Range(int low, int high) {

	// compiler knows signature and assigns to fields
	public Range {
		if (low > high)
			throw new IllegalArgumentException();
	}

	public void setLow(int low) {
		if (low > this.high)
			throw new IllegalArgumentException();
		this.low = low;
	}

}

Death to serialization!

Serialization is hell:

  • complicates every JDK feature

  • repeated security vulnerabilities

  • uses "invisible" mechanisms

The JDK team wants to get rid of it!

Serializing records

Replacement may look as follows:

  • only works with records

  • deconstructs a record graph

  • passes data to serilization engine

  • one engine per format:
    XML, JSON, YAML, …​

New serialization

Yeah:

  • records are a great fit for serialization

  • new mechanism uses (de)constructors

  • superior maintainability

Concise method bodies

class ListWrapper<E> implements List<E> {

    private List<E> list;

    public int size() -> list.size();
    public T get(int index) -> list.get(index);
	public int indexOf(E el) = list::indexOf;

}

Yeah:

  • simple methods get simple code

  • fewer (empty) lines

Project Amber

Makes Java more expressive:

  • type inference with var ⑩

  • raw string literals ⑫

  • switch expressions ⑫

  • pattern matching

  • records

  • revamps serialization

  • concise method bodies

Project Valhalla

Advanced Java VM and Language feature candidates

Profile:

Motivation

In Java, (almost) everything is a class:

  • mutable by default

  • memory access indirection

  • requires extra memory for header

  • allows locking and other
    identity-based operations

Wouldn’t it be nice to create a custom int?

Value types

public value Range {

	// implicitly final
	private int low;
	private int high;

	// you write:
	//  * constructor, static factories
	//  * equals/hashCode/toString
	//  * accessors, etc.

}

Value types

public value Range {
	private int low;
	private int high;
}

Yeah:

  • enforced immutability

  • no memory indirection! (flat)

  • no Object header! (dense)

  • makes Java more expressive

Value types

Codes like a class, works like an int.

The deal:

  • give up identity / mutability
    (and self references)

  • get flat and dense memory layout

Values vs Records

Values

no identity / mutability
⇝ flat and dense memory layout

Records

no encapsulation
⇝ less boilerplate

Might be combinable to "value records".

Generic specialization

When everybody creates their own "primitives",
boxing becomes omni-present and very painful!

List<int> ids = new ArrayList<>();

Yeah:

  • backed by an actual int[]

  • great performance

  • works with your value types

Put together

Value types and generic specialization together,
have immense effects inside the JDK!

  • no more manual specializations:

    • functional interfaces

    • stream API

    • Optional API

  • better performance

Put together

Value types and generic specialization together,
have immense effects on your code!

  • fewer trade-offs between
    design and performance

  • better performance

  • can express design more clearly

  • more robust APIs

Project Valhalla

Makes Java more expressive and performant:

  • value types

  • primitive specialization

Project Loom

Fibers, delimited continuations, explicit tail-call

Profile:

Motivation

Imagine a hypothetical request:

  1. interpret request

  2. query database (blocks)

  3. process data for response

JVM resource utilization:

  • good for tasks 1., 3.

  • really bad for task 2.

How to implement that request?

Motivation

Synchronous (simple)
  • thread per request

  • blocks on certain calls

  • bad thread utilization

Asynchronous (not so simple)
  • use non-blocking APIs with futures

  • incompatible with synchronous code

  • great thread utilization (scalable!)

Enter fibers!

A fiber:

  • looks like a thread to devs

  • low memory footprint ([k]bytes)

  • small switching cost

  • scheduled by the JVM

Fiber management

The JVM manages fibers:

  • runs them in a pool of carrier threads

  • makes fibers yield on blocking calls
    (frees the carrier thread!)

  • continues fibers when calls return

Fiber example

Remember the hypothetical request:

  1. interpret request

  2. query database (blocks)

  3. process data for response

In a fiber:

  • JVM submits fiber to thread pool

  • when 2. blocks, fiber yields

  • JVM hands thread back to pool

  • when 2. unblocks, JVM resubmits fiber

  • fiber continues with 3. (how?)

Fibers

Yeah:

  • great thread utilization

  • code is written/debugged as if synchronous

  • legacy code may be forward compatible

Continuations

How do fibers continue?

  • use continuations (low-level API)

  • JVM stores and restores call stack

Project Loom

Makes threading more pleasant:

  • simple programming model

  • great thread utilization

Projects

To know what’s coming:

  • pick a project that interests you

  • look out for mentions

  • subscribe to the mailing list

  • find early access builds and try them

  • give feedback

Tell your colleagues about it!

About Nicolai Parlog

37% off with
code fccparlog

tiny.cc/jms

Follow

💻 codefx.org
▶ youtube.com/c/codefx
🐦 @nipafx

Want More?

⇜ Get my book!

You can hire me:

  • training (Java 8-11, JUnit 5)

  • consulting (Java 8-11)

Image Credits

Image Credits