KEMBAR78
Modern Java Workshop | PPTX
OpenJDK 17: Get Ready
For the Next LTS Java
Presented by Simon Ritter, Deputy CTO | Azul Systems Inc.
2
Introduction
Java has changed…
…a lot
• Six-month release cadence
• Eight releases since JDK 9
• More features being delivered faster than ever before
• This session will explore new features added since JDK 11
• Helping you to be ready for JDK 17, the next LTS release
3
A Brief Word on JDK Licensing
• Since JDK 11, the Oracle JDK uses a new license
o Oracle Technology Network License Agreement
• More restrictive in where it can be used freely
o Personal or development use
o Oracle approved applications and Oracle Cloud use
o Any other use requires a Java SE subscription to be purchased
• There are many alternative binary distributions of OpenJDK
o More on this later…
4
Incubator Modules
• Defined by JEP 11
• Non-final APIs and non-final tools
o Deliver to developers to solicit feedback
o Can result in changes or even removal
o First example: HTTP/2 API (Introduced in JDK 9, final in JDK 11)
5
Preview Features
• Defined by JEP 12
• New feature of the Java language, JVM or Java SE APIs
o Fully specified, fully implemented but not permanent
o Solicit developer real-world use and experience
o May lead to becoming a permanent feature in future release
• Must be explicitly enabled
o javac --release 17 --enable-preview ...
o java --enable-preview ...
• Preview APIs
o May be required for a preview language feature
o Part of the Java SE API (java or javax namespace)
JDK 12
7
Switch Expressions (Preview)
• Switch construct was a statement
o No concept of generating a result that could be assigned
• Rather clunky syntax
o Every case statement needs to be separated
o Must remember break (default is to fall through)
o Scope of local variables is not intuitive
8
Old-Style Switch Statement
int numberOfLetters;
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numberOfLetters = 6;
break;
case TUESDAY:
numberOfLetters = 7;
break;
case THURSDAY:
case SATURDAY:
numberOfLetters = 8;
break;
case WEDNESDAY:
numberOfLetters = 9;
break;
default:
throw new IllegalStateException("Huh?: " + day); };
9
New-Style Switch Expression
int numberOfLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
default -> throw new IllegalStateException("Huh?: " + day);
};
10
New Old-Style Switch Expression
int numberOfLetters = switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
break 6;
case TUESDAY
break 7;
case THURSDAY
case SATURDAY
break 8;
case WEDNESDAY
break 9;
default:
throw new IllegalStateException("Huh?: " + day);
};
11
Switch Expression: Code Blocks
int levelResult = switch (level) {
case 1 -> {
var x = computeFrom(level);
logger.info("Level 1 alert");
break x;
}
case 2 -> {
var x = negativeComputeFrom(level);
logger.info("Level 2 alert");
break x;
}
default -> throw new IllegalStateException("What level?: " + level);
};
12
Streams
• New collector, teeing
o teeing(Collector, Collector, BiFunction)
• Collect a stream using two collectors
• Use a BiFunction to merge the two collections
Collector 1
Collector 2
BiFunction
Stream Result
13
Streams
// Averaging
Double average = Stream.of(1, 4, 5, 2, 1, 7)
.collect(teeing(summingDouble(i -> i), counting(),
(sum, n) -> sum / n));
JDK 13
15
Text Blocks (Preview)
String webPage = """
<html>
<body>
<p>My web page</p>
</body>
</html> """;
System.out.println(webPage);
$ java WebPage
<html>
<body>
<p>My web page</p>
</body>
</html>
$
incidental white space
Must be followed by newline
Any trailing whitespace is stripped
16
Text Blocks (Preview)
String webPage = """
<html>
<body>
<p>My web page</p>
</body>
</html>
""";
System.out.println(webPage);
$ java WebPage
<html>
<body>
<p>My web page</p>
</body>
</html>
$
Additional blank line
incidental white space
Intentional indentation
17
Switch Expression
int numberOfLetters = switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
break 6;
case TUESDAY
break 7;
case THURSDAY
case SATURDAY
break 8;
case WEDNESDAY
break 9;
default:
throw new IllegalStateException("Huh?: " + day);
};
18
Switch Expression
int numberOfLetters = switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
yield 6;
case TUESDAY
yield 7;
case THURSDAY
case SATURDAY
yield 8;
case WEDNESDAY
yield 9;
default:
throw new IllegalStateException("Huh?: " + day);
};
JDK 14
20
Simple Java Data Class
class Point {
private final double x;
private final double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double x() {
return x;
}
public double y() {
return y;
}
}
21
Records (Preview)
record Point(double x, double y) { }
record Anything<T>(T t) { } // Generic Record
public record Circle(double radius) {
private static final double PI = 3.142; // Static instance fields are allowed
public double area() {
return radius * PI;
}
}
22
Record Additional Details
• The base class of all records is java.lang.Record
o Records cannot sub-class (but may implement interfaces)
• Object methods equals(), hashCode() and toString() can be overridden
• Records are implicitly final (although you may add the modifier)
• Records do not follow the Java bean pattern
o x() not getX() in Point example
o record Point(getX, getY) // If you must
23
Record Constructors
record Trex(int x, int y) {
public Trex(int x, int y) { // Canonical constructor
if (x < y)
System.out.println("inverted values");
this.x = x; // This line needed
this.y = y; // This line needed
}
}
record Range(int low, int high) {
public Range { // Compact constructor
if (low > high)
throw new IllegalArgumentException("Bad values");
}
}
Compact constructor can only
throw unchecked exception
24
Record Constructors
record Trex(int x, int y) {
public Trex(int x, int y, int z) throws TrexException { // Standard constructor
this(x, y); // This line must be present
if (x < y)
throw new TrexException(); // Checked Exception
}
}
Constructor signature must be
different to canonical
25
Record Default Constructor
record Trex(int x, int y) {
public Trex() { // Default constructor
this(2, 3); // This line must be present
}
}
26
Using instanceof
if (obj instanceof String) {
String s = (String)obj;
System.out.println(s.length());
}
27
Pattern Matching instanceof (Preview)
if (obj instanceof String s)
System.out.println(s.length());
else
// Use of s not allowed here
if (obj instanceof String s && s.length() > 0)
System.out.println(s.length());
// Compiler error
if (obj instanceof String s || s.length() > 0)
System.out.println(s.length());
28
Pattern Matching instanceof (Preview)
• Uses flow scoping
if (!(o instanceof String s)
return;
System.out.println(s.length());
29
Pattern Matching instanceof (JEP 394)
• Be careful of scope!
29
class BadPattern {
String s = "One";
void testMyObject(Object o) {
if (o instanceof String s) {
System.out.println(s); // Prints contents of o
s = s + " Two"; // Modifies pattern variable
}
System.out.println(s); // Prints "One"
}
}
30
Text Blocks
• Second preview
• Two new escape sequences
String continuous = """
This line will not 
contain a newline in the middle
and solves the extra blank line issue 
""";
String endSpace = """
This line will not s
lose the trailing spaces s""";
31
Foreign-Memory Access API (JEP 393)
• API for safe and efficient access to memory outside of the Java heap
• MemorySegment
o Models a contiguous area of memory
• MemoryAddress
o Models an individual memory address (on or off heap)
• MemoryLayout
o Programmatic description of a MemorySegment
31
try (MemorySegment segment = MemorySegment.allocateNative(100)) {
for (int i = 0; i < 25; i++)
MemoryAccess.setIntAtOffset(segment, i * 4, i);
}
32
Foreign-Memory Access API (JEP 393)
• Example using MemoryLayout and VarHandle
o Simpler access of structured data
32
SequenceLayout intArrayLayout
= MemoryLayout.ofSequence(25,
MemoryLayout.ofValueBits(32,
ByteOrder.nativeOrder()));
VarHandle indexedElementHandle
= intArrayLayout.varHandle(int.class,
PathElement.sequenceElement());
try (MemorySegment segment = MemorySegment.allocateNative(intArrayLayout)) {
for (int i = 0; i < intArrayLayout.elementCount().getAsLong(); i++)
indexedElementHandle.set(segment, (long) i, i);
}
33
Helpful NullPointerException
• Who's never had an NullPointerException?
• Enabled with -XX:+ShowCodeDetailsInExceptionMessages
a.b.c.i = 99;
Exception in thread "main" java.lang.NullPointerException
at Prog.main(Prog.java:5)
Exception in thread "main" java.lang.NullPointerException:
Cannot read field "c" because "a.b" is null
at Prog.main(Prog.java:5)
34
Packaging Tool
• Originally part of JavaFX, which was removed in JDK 11
• Leverages other tools
o jlink for minimised JDK
o Platform specific packaging tools like rpm on Linux, pkg on Mac
• Multiple command line options
jpackage 
--name PDFShow 
--app-version ${RELEASE_VERSION} 
--license-file LICENSE.txt 
--vendor "${COMPANY_NAME}" 
--type "${inst_format}" 
--icon src/main/resources/images/logo.${icon_format} 
--input target 
--main-jar pdfshow-${RELEASE_VERSION}-jar-with-dependencies.jar 
--linux-shortcut --linux-menu-group Office
JDK 15
36
Java Inheritance
• A class (or interface) in Java can be sub-classed by any class
o Unless it is marked as final
Shape
Triangle Square Pentagon
37
Sealed Classes (JEP 360)
• Preview feature
• Sealed classes allow control over which classes can sub-class a class
o Think of final as the ultimate sealed class
• Although called sealed classes, this also applies to interfaces
38
Sealed Classes (JEP 360)
• Uses contextual keywords
o New idea replacing restricted identifiers and keywords
o sealed, permits and non-sealed
• Classes must all be in the same package or module
public sealed class Shape permits Triangle, Square, Pentagon { ... }
Shape
Triangle Square Pentagon Circle
X
39
Sealed Classes (JEP 360)
• All sub-classes must have inheritance capabilities explicitly specified
// Restrict sub-classes to defined set
public sealed class Triangle permits Equilateral, Isosoles extends Shape { ... }
// Prevent any further sub-classing
public final class Square extends Shape { ... }
// Allow any classes to sub-class this one (open)
public non-sealed class Pentagon extends Shape { ... }
40
Records (Second Preview)
• Record fields are now (really) final
o Cannot be changed via reflection (will throw IllegalAccessException)
• Native methods now explicitly prohibited
o Could introduce behaviour dependent on external state
41
Records (Second Preview)
• Local records
o Like a local class
o Implicitly static (also now applies to enums and interfaces)
List<Seller> findTopSellers(List<Seller> sellers, int month) {
// Local record
record Sales(Seller seller, double sales) {}
return sellers.stream()
.map(seller -> new Sales(seller, salesInMonth(seller, month)))
.sorted((s1, s2) -> Double.compare(s2.sales(), s1.sales()))
.map(Sales::seller)
.collect(toList());
}
42
Records (Second Preview)
• Records work with sealed classes (interfaces)
public sealed interface Car permits RedCar, BlueCar { ... }
public record RedCar(int w) implements Car { ... }
public record BlueCar(long w, int c) implements Car { ... }
JDK 16
44
Pattern Matching instanceof
• Now a final feature (as are Records in JDK 16)
• Two minor changes to previous iterations
o Pattern variables are no longer explicitly final
o Compile-time error to compare an expression of type S against a pattern of type T where S is a sub-type of T
static void printColoredPoint(Rectangle r) {
if (r instanceof Rectangle rect) {
System.out.println(rect);
}
}
| Error:
| pattern type Rectangle is a subtype of expression type Rectangle
| if (r instanceof Rectangle rect) {
| ^-------------------------^
45
Streams mapMulti
• Similar to flatMap
o Each element on the input stream is mapped to zero or more elements on the output stream
o Difference is that a mapping can be applied at the same time
o Uses a BiConsumer
• 1 to (0..1) example
45
Stream.of("Java", "Python", "JavaScript", "C#", "Ruby")
.mapMulti((str, consumer) -> {
if (str.length() > 4)
consumer.accept(str.length()); // lengths larger than 4
})
.forEach(i -> System.out.print(i + " "));
// 6 10
46
Stream mapMulti
• 1 to 1 example
46
Stream.of("Java", "Python", "JavaScript", "C#", "Ruby")
.mapMulti((str, consumer) -> consumer.accept(str.length()))
.forEach(i -> System.out.print(i + " "));
// 4 6 10 2 4
47
Stream mapMulti
• 1 to many example
47
Stream.of("Java", "Python", "JavaScript", "C#", "Ruby", "")
.mapMulti((str, consumer) -> {
for (int i = 0; i < str.length(); i++)
consumer.accept(str.length());
})
.forEach(i -> System.out.print(i + " "));
// 4 4 4 4 6 6 6 6 6 6 10 10 10 10 10 10 10 10 10 10 2 2 4 4 4 4
48
Stream toList()
• Simplified terminal operation that avoids explicit use of collect()
List l = Stream.of(1, 2, 3)
.collect(Collectors.toList());
List l = Stream.of(1, 2, 3)
.toList();
49
Period of Day
• More variation than simple A.M. or P.M.
• More descriptive
jshell> DateTimeFormatter.ofPattern("B").format(LocalTime.now())
$3 ==> "in the afternoon"
50
Vector API (Incubator Module)
• Not to be confused with the Vector collection class
• API to express vector computations
o Compile at runtime to optimal hardware instructions
o Deliver superior performance to equivalent scalar operations
• Ideally, this would not be necessary
o Compiler should identify where vector operations can be used
50
10
14
11
8
12
16
13
10
+2
+2
+2
+2
10 14 11 8
+2
12 16 13 10
+2
+2 +2
51
Code Example
private void addArraysIfEven(int a[], int b[]) {
for (int i = 0; i < a.length; i++)
if ((b[i] & 0x1) == 0)
a[i] += b[i];
}
52
Generated Code (No Vector API)
Loop unrolling
no vector instructions
53
Code Example With Vector API
private void addArraysIfEven(int a[], int b[]) {
VectorSpecies<Integer> species = IntVector.SPECIES_256;
for (int i = 0; i < a.length; i += species.length()) {
if ((b[i] & 0x1) == 0) {
var mask = species.indexInRange(i, a.length);
var vectorA = IntVector.fromArray(species, a, i, mask);
var vectorB = IntVector.fromArray(species, b, i, mask);
var vectorC = vectorA.add(vectorB);
vectorC.intoArray(a, i, mask);
}
}
}
54
Generated Code (Vector API)
Loop unrolling
plus vector instructions
55
Foreign Linker API (JEP 389): Incubator
• Provides statically-typed, pure-Java access to native code
o Works in conjunction with the Foreign Memory Access API
o Initially targeted at C native code. C++ should follow
• More powerful when combined with Project Panama jextract command
55
public static void main(String[] args) throws Throwable {
var linker = CLinker.getInstance();
var lookup = LibraryLookup.ofDefault();
// get a native method handle for 'getpid' function
var getpid = linker.downcallHandle(lookup.lookup("getpid").get(),
MethodType.methodType(int.class),
FunctionDescriptor.of(CLinker.C_INT));
System.out.println((int)getpid.invokeExact());
}
56
Warnings for Value-Based Classes
• Part of Project Valhalla, which adds value-types to Java
o Introduces the concept of primitive classes
• Primitive wrapper classes (Integer, Float, etc.) designated value-based
o Constructors were deprecated in JDK 9
o Now marked as for removal
o Attempting to synchronize on an instance of a value-based class will issue a warning
56
JDK 17
58
Pattern Matching for switch
• Switch is limited on what types you can use (Integral values, Strings, enumerations)
• This is now expanded to allow type patterns to be matched
o Like pattern matching for instanceof
void typeTester(Object o) {
switch (o) {
case null -> System.out.println("Null type");
case String s -> System.out.println("String: " + s);
case Color c -> System.out.println("Color with RGB: " + c.getRGB());
case int[] ia -> System.out.println("Array of ints, length" + ia.length);
default -> System.out.println(o.toString());
}
}
59
Pattern Matching for switch (Completeness)
void typeTester(Object o) {
switch (o) {
case String s -> System.out.println("String: " + s);
case Integer i -> System.out.println("Integer with value " + i.getInteger());
}
}
void typeTester(Object o) {
switch (o) {
case String s -> System.out.println("String: " + s);
case Integer i -> System.out.println("Integer with value " + i.getInteger());
default -> System.out.println("Some other type");
}
}
void typeTester(Shape shape) { // Using previous sealed class example
switch (shape) {
case Triangle t -> System.out.println("It's a triangle");
case Square s -> System.out.println("It's a square");
case Pentagon p -> System.out.println("It's a pentagon");
}
}
60
Guarded Patterns
void shapeTester(Shape shape) { // Using previous sealed class example
switch (shape) {
case Triangle t && t.area() > 25 -> System.out.println("It's a big triangle");
case Triangle t -> System.out.println("It's a small triangle");
case Square s -> System.out.println("It's a square");
case Pentagon p -> System.out.println("It's a pentagon");
}
}
GuardedPattern:
PrimaryPattern && ConditionalAndExpression
Compatability
Issues
62
Removed From The JDK
• JDK 14: CMS Garbage Collector
o You should really be using G1 (or Azul Prime)
• JDK 15: Nashorn scripting engine
o JavaScript from Java?
• JDK 17: Experimental AOT and JIT compilers
o Didn't shown much appeal
• JDK 17: Deprecate the Security Manager for removal
o No, it doesn't make Java less secure
63
Internal JDK APIs
• JDK 9 introduced encapsulation of internal JDK APIs
o Never intended for general developer use
o Too difficult for backwards compatibility
- Off by default
- Controlled by --illegal-access flag
• JDK 16 took this one step further
o Default became deny access
o Access could still be turned back on
• JDK 17 completes strong encapsulation (almost)
o The --illegal-access flag now has no effect (just a warning)
o Critical APIs (like sun.misc.Unsafe) are still accessible
Summary
65
Azul Platform Core / Azul Zulu Builds of OpenJDK
• Enhanced build of OpenJDK source code
o Fully TCK tested
o JDK 6, 7, 8, 11, 13 and 15 supported with updates
• Wide platform support:
o Intel 64-bit Windows, Mac, Linux
o Intel 32-bit Windows and Linux
• Real drop-in replacement for Oracle JDK
o Many enterprise customers
o No reports of any compatibility issues
66
Azul Platform Core Extended Support
• Backporting of bug fixes and security patches from supported OpenJDK release
• Azul Zulu Builds of OpenJDK 8 supported until December 2030
• LTS releases have 9 years active + 2 years passive support
• JDK 15 is a Medium Term Support release
o Bridge to next LTS release (JDK 17)
o Supported until 18 months after JDK 17 release
67
Conclusions
• The six-month release cycle is working well
• The language is developing to address some developerpain-points
• There are some other new features we have not been able to cover
o JVM specific things
• Use Azul Platform Core, with Azul Zulu builds of OpenJDK, if you want to deploy to production
Questions?

Modern Java Workshop

  • 1.
    OpenJDK 17: GetReady For the Next LTS Java Presented by Simon Ritter, Deputy CTO | Azul Systems Inc.
  • 2.
    2 Introduction Java has changed… …alot • Six-month release cadence • Eight releases since JDK 9 • More features being delivered faster than ever before • This session will explore new features added since JDK 11 • Helping you to be ready for JDK 17, the next LTS release
  • 3.
    3 A Brief Wordon JDK Licensing • Since JDK 11, the Oracle JDK uses a new license o Oracle Technology Network License Agreement • More restrictive in where it can be used freely o Personal or development use o Oracle approved applications and Oracle Cloud use o Any other use requires a Java SE subscription to be purchased • There are many alternative binary distributions of OpenJDK o More on this later…
  • 4.
    4 Incubator Modules • Definedby JEP 11 • Non-final APIs and non-final tools o Deliver to developers to solicit feedback o Can result in changes or even removal o First example: HTTP/2 API (Introduced in JDK 9, final in JDK 11)
  • 5.
    5 Preview Features • Definedby JEP 12 • New feature of the Java language, JVM or Java SE APIs o Fully specified, fully implemented but not permanent o Solicit developer real-world use and experience o May lead to becoming a permanent feature in future release • Must be explicitly enabled o javac --release 17 --enable-preview ... o java --enable-preview ... • Preview APIs o May be required for a preview language feature o Part of the Java SE API (java or javax namespace)
  • 6.
  • 7.
    7 Switch Expressions (Preview) •Switch construct was a statement o No concept of generating a result that could be assigned • Rather clunky syntax o Every case statement needs to be separated o Must remember break (default is to fall through) o Scope of local variables is not intuitive
  • 8.
    8 Old-Style Switch Statement intnumberOfLetters; switch (day) { case MONDAY: case FRIDAY: case SUNDAY: numberOfLetters = 6; break; case TUESDAY: numberOfLetters = 7; break; case THURSDAY: case SATURDAY: numberOfLetters = 8; break; case WEDNESDAY: numberOfLetters = 9; break; default: throw new IllegalStateException("Huh?: " + day); };
  • 9.
    9 New-Style Switch Expression intnumberOfLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; default -> throw new IllegalStateException("Huh?: " + day); };
  • 10.
    10 New Old-Style SwitchExpression int numberOfLetters = switch (day) { case MONDAY: case FRIDAY: case SUNDAY: break 6; case TUESDAY break 7; case THURSDAY case SATURDAY break 8; case WEDNESDAY break 9; default: throw new IllegalStateException("Huh?: " + day); };
  • 11.
    11 Switch Expression: CodeBlocks int levelResult = switch (level) { case 1 -> { var x = computeFrom(level); logger.info("Level 1 alert"); break x; } case 2 -> { var x = negativeComputeFrom(level); logger.info("Level 2 alert"); break x; } default -> throw new IllegalStateException("What level?: " + level); };
  • 12.
    12 Streams • New collector,teeing o teeing(Collector, Collector, BiFunction) • Collect a stream using two collectors • Use a BiFunction to merge the two collections Collector 1 Collector 2 BiFunction Stream Result
  • 13.
    13 Streams // Averaging Double average= Stream.of(1, 4, 5, 2, 1, 7) .collect(teeing(summingDouble(i -> i), counting(), (sum, n) -> sum / n));
  • 14.
  • 15.
    15 Text Blocks (Preview) StringwebPage = """ <html> <body> <p>My web page</p> </body> </html> """; System.out.println(webPage); $ java WebPage <html> <body> <p>My web page</p> </body> </html> $ incidental white space Must be followed by newline Any trailing whitespace is stripped
  • 16.
    16 Text Blocks (Preview) StringwebPage = """ <html> <body> <p>My web page</p> </body> </html> """; System.out.println(webPage); $ java WebPage <html> <body> <p>My web page</p> </body> </html> $ Additional blank line incidental white space Intentional indentation
  • 17.
    17 Switch Expression int numberOfLetters= switch (day) { case MONDAY: case FRIDAY: case SUNDAY: break 6; case TUESDAY break 7; case THURSDAY case SATURDAY break 8; case WEDNESDAY break 9; default: throw new IllegalStateException("Huh?: " + day); };
  • 18.
    18 Switch Expression int numberOfLetters= switch (day) { case MONDAY: case FRIDAY: case SUNDAY: yield 6; case TUESDAY yield 7; case THURSDAY case SATURDAY yield 8; case WEDNESDAY yield 9; default: throw new IllegalStateException("Huh?: " + day); };
  • 19.
  • 20.
    20 Simple Java DataClass class Point { private final double x; private final double y; public Point(double x, double y) { this.x = x; this.y = y; } public double x() { return x; } public double y() { return y; } }
  • 21.
    21 Records (Preview) record Point(doublex, double y) { } record Anything<T>(T t) { } // Generic Record public record Circle(double radius) { private static final double PI = 3.142; // Static instance fields are allowed public double area() { return radius * PI; } }
  • 22.
    22 Record Additional Details •The base class of all records is java.lang.Record o Records cannot sub-class (but may implement interfaces) • Object methods equals(), hashCode() and toString() can be overridden • Records are implicitly final (although you may add the modifier) • Records do not follow the Java bean pattern o x() not getX() in Point example o record Point(getX, getY) // If you must
  • 23.
    23 Record Constructors record Trex(intx, int y) { public Trex(int x, int y) { // Canonical constructor if (x < y) System.out.println("inverted values"); this.x = x; // This line needed this.y = y; // This line needed } } record Range(int low, int high) { public Range { // Compact constructor if (low > high) throw new IllegalArgumentException("Bad values"); } } Compact constructor can only throw unchecked exception
  • 24.
    24 Record Constructors record Trex(intx, int y) { public Trex(int x, int y, int z) throws TrexException { // Standard constructor this(x, y); // This line must be present if (x < y) throw new TrexException(); // Checked Exception } } Constructor signature must be different to canonical
  • 25.
    25 Record Default Constructor recordTrex(int x, int y) { public Trex() { // Default constructor this(2, 3); // This line must be present } }
  • 26.
    26 Using instanceof if (objinstanceof String) { String s = (String)obj; System.out.println(s.length()); }
  • 27.
    27 Pattern Matching instanceof(Preview) if (obj instanceof String s) System.out.println(s.length()); else // Use of s not allowed here if (obj instanceof String s && s.length() > 0) System.out.println(s.length()); // Compiler error if (obj instanceof String s || s.length() > 0) System.out.println(s.length());
  • 28.
    28 Pattern Matching instanceof(Preview) • Uses flow scoping if (!(o instanceof String s) return; System.out.println(s.length());
  • 29.
    29 Pattern Matching instanceof(JEP 394) • Be careful of scope! 29 class BadPattern { String s = "One"; void testMyObject(Object o) { if (o instanceof String s) { System.out.println(s); // Prints contents of o s = s + " Two"; // Modifies pattern variable } System.out.println(s); // Prints "One" } }
  • 30.
    30 Text Blocks • Secondpreview • Two new escape sequences String continuous = """ This line will not contain a newline in the middle and solves the extra blank line issue """; String endSpace = """ This line will not s lose the trailing spaces s""";
  • 31.
    31 Foreign-Memory Access API(JEP 393) • API for safe and efficient access to memory outside of the Java heap • MemorySegment o Models a contiguous area of memory • MemoryAddress o Models an individual memory address (on or off heap) • MemoryLayout o Programmatic description of a MemorySegment 31 try (MemorySegment segment = MemorySegment.allocateNative(100)) { for (int i = 0; i < 25; i++) MemoryAccess.setIntAtOffset(segment, i * 4, i); }
  • 32.
    32 Foreign-Memory Access API(JEP 393) • Example using MemoryLayout and VarHandle o Simpler access of structured data 32 SequenceLayout intArrayLayout = MemoryLayout.ofSequence(25, MemoryLayout.ofValueBits(32, ByteOrder.nativeOrder())); VarHandle indexedElementHandle = intArrayLayout.varHandle(int.class, PathElement.sequenceElement()); try (MemorySegment segment = MemorySegment.allocateNative(intArrayLayout)) { for (int i = 0; i < intArrayLayout.elementCount().getAsLong(); i++) indexedElementHandle.set(segment, (long) i, i); }
  • 33.
    33 Helpful NullPointerException • Who'snever had an NullPointerException? • Enabled with -XX:+ShowCodeDetailsInExceptionMessages a.b.c.i = 99; Exception in thread "main" java.lang.NullPointerException at Prog.main(Prog.java:5) Exception in thread "main" java.lang.NullPointerException: Cannot read field "c" because "a.b" is null at Prog.main(Prog.java:5)
  • 34.
    34 Packaging Tool • Originallypart of JavaFX, which was removed in JDK 11 • Leverages other tools o jlink for minimised JDK o Platform specific packaging tools like rpm on Linux, pkg on Mac • Multiple command line options jpackage --name PDFShow --app-version ${RELEASE_VERSION} --license-file LICENSE.txt --vendor "${COMPANY_NAME}" --type "${inst_format}" --icon src/main/resources/images/logo.${icon_format} --input target --main-jar pdfshow-${RELEASE_VERSION}-jar-with-dependencies.jar --linux-shortcut --linux-menu-group Office
  • 35.
  • 36.
    36 Java Inheritance • Aclass (or interface) in Java can be sub-classed by any class o Unless it is marked as final Shape Triangle Square Pentagon
  • 37.
    37 Sealed Classes (JEP360) • Preview feature • Sealed classes allow control over which classes can sub-class a class o Think of final as the ultimate sealed class • Although called sealed classes, this also applies to interfaces
  • 38.
    38 Sealed Classes (JEP360) • Uses contextual keywords o New idea replacing restricted identifiers and keywords o sealed, permits and non-sealed • Classes must all be in the same package or module public sealed class Shape permits Triangle, Square, Pentagon { ... } Shape Triangle Square Pentagon Circle X
  • 39.
    39 Sealed Classes (JEP360) • All sub-classes must have inheritance capabilities explicitly specified // Restrict sub-classes to defined set public sealed class Triangle permits Equilateral, Isosoles extends Shape { ... } // Prevent any further sub-classing public final class Square extends Shape { ... } // Allow any classes to sub-class this one (open) public non-sealed class Pentagon extends Shape { ... }
  • 40.
    40 Records (Second Preview) •Record fields are now (really) final o Cannot be changed via reflection (will throw IllegalAccessException) • Native methods now explicitly prohibited o Could introduce behaviour dependent on external state
  • 41.
    41 Records (Second Preview) •Local records o Like a local class o Implicitly static (also now applies to enums and interfaces) List<Seller> findTopSellers(List<Seller> sellers, int month) { // Local record record Sales(Seller seller, double sales) {} return sellers.stream() .map(seller -> new Sales(seller, salesInMonth(seller, month))) .sorted((s1, s2) -> Double.compare(s2.sales(), s1.sales())) .map(Sales::seller) .collect(toList()); }
  • 42.
    42 Records (Second Preview) •Records work with sealed classes (interfaces) public sealed interface Car permits RedCar, BlueCar { ... } public record RedCar(int w) implements Car { ... } public record BlueCar(long w, int c) implements Car { ... }
  • 43.
  • 44.
    44 Pattern Matching instanceof •Now a final feature (as are Records in JDK 16) • Two minor changes to previous iterations o Pattern variables are no longer explicitly final o Compile-time error to compare an expression of type S against a pattern of type T where S is a sub-type of T static void printColoredPoint(Rectangle r) { if (r instanceof Rectangle rect) { System.out.println(rect); } } | Error: | pattern type Rectangle is a subtype of expression type Rectangle | if (r instanceof Rectangle rect) { | ^-------------------------^
  • 45.
    45 Streams mapMulti • Similarto flatMap o Each element on the input stream is mapped to zero or more elements on the output stream o Difference is that a mapping can be applied at the same time o Uses a BiConsumer • 1 to (0..1) example 45 Stream.of("Java", "Python", "JavaScript", "C#", "Ruby") .mapMulti((str, consumer) -> { if (str.length() > 4) consumer.accept(str.length()); // lengths larger than 4 }) .forEach(i -> System.out.print(i + " ")); // 6 10
  • 46.
    46 Stream mapMulti • 1to 1 example 46 Stream.of("Java", "Python", "JavaScript", "C#", "Ruby") .mapMulti((str, consumer) -> consumer.accept(str.length())) .forEach(i -> System.out.print(i + " ")); // 4 6 10 2 4
  • 47.
    47 Stream mapMulti • 1to many example 47 Stream.of("Java", "Python", "JavaScript", "C#", "Ruby", "") .mapMulti((str, consumer) -> { for (int i = 0; i < str.length(); i++) consumer.accept(str.length()); }) .forEach(i -> System.out.print(i + " ")); // 4 4 4 4 6 6 6 6 6 6 10 10 10 10 10 10 10 10 10 10 2 2 4 4 4 4
  • 48.
    48 Stream toList() • Simplifiedterminal operation that avoids explicit use of collect() List l = Stream.of(1, 2, 3) .collect(Collectors.toList()); List l = Stream.of(1, 2, 3) .toList();
  • 49.
    49 Period of Day •More variation than simple A.M. or P.M. • More descriptive jshell> DateTimeFormatter.ofPattern("B").format(LocalTime.now()) $3 ==> "in the afternoon"
  • 50.
    50 Vector API (IncubatorModule) • Not to be confused with the Vector collection class • API to express vector computations o Compile at runtime to optimal hardware instructions o Deliver superior performance to equivalent scalar operations • Ideally, this would not be necessary o Compiler should identify where vector operations can be used 50 10 14 11 8 12 16 13 10 +2 +2 +2 +2 10 14 11 8 +2 12 16 13 10 +2 +2 +2
  • 51.
    51 Code Example private voidaddArraysIfEven(int a[], int b[]) { for (int i = 0; i < a.length; i++) if ((b[i] & 0x1) == 0) a[i] += b[i]; }
  • 52.
    52 Generated Code (NoVector API) Loop unrolling no vector instructions
  • 53.
    53 Code Example WithVector API private void addArraysIfEven(int a[], int b[]) { VectorSpecies<Integer> species = IntVector.SPECIES_256; for (int i = 0; i < a.length; i += species.length()) { if ((b[i] & 0x1) == 0) { var mask = species.indexInRange(i, a.length); var vectorA = IntVector.fromArray(species, a, i, mask); var vectorB = IntVector.fromArray(species, b, i, mask); var vectorC = vectorA.add(vectorB); vectorC.intoArray(a, i, mask); } } }
  • 54.
    54 Generated Code (VectorAPI) Loop unrolling plus vector instructions
  • 55.
    55 Foreign Linker API(JEP 389): Incubator • Provides statically-typed, pure-Java access to native code o Works in conjunction with the Foreign Memory Access API o Initially targeted at C native code. C++ should follow • More powerful when combined with Project Panama jextract command 55 public static void main(String[] args) throws Throwable { var linker = CLinker.getInstance(); var lookup = LibraryLookup.ofDefault(); // get a native method handle for 'getpid' function var getpid = linker.downcallHandle(lookup.lookup("getpid").get(), MethodType.methodType(int.class), FunctionDescriptor.of(CLinker.C_INT)); System.out.println((int)getpid.invokeExact()); }
  • 56.
    56 Warnings for Value-BasedClasses • Part of Project Valhalla, which adds value-types to Java o Introduces the concept of primitive classes • Primitive wrapper classes (Integer, Float, etc.) designated value-based o Constructors were deprecated in JDK 9 o Now marked as for removal o Attempting to synchronize on an instance of a value-based class will issue a warning 56
  • 57.
  • 58.
    58 Pattern Matching forswitch • Switch is limited on what types you can use (Integral values, Strings, enumerations) • This is now expanded to allow type patterns to be matched o Like pattern matching for instanceof void typeTester(Object o) { switch (o) { case null -> System.out.println("Null type"); case String s -> System.out.println("String: " + s); case Color c -> System.out.println("Color with RGB: " + c.getRGB()); case int[] ia -> System.out.println("Array of ints, length" + ia.length); default -> System.out.println(o.toString()); } }
  • 59.
    59 Pattern Matching forswitch (Completeness) void typeTester(Object o) { switch (o) { case String s -> System.out.println("String: " + s); case Integer i -> System.out.println("Integer with value " + i.getInteger()); } } void typeTester(Object o) { switch (o) { case String s -> System.out.println("String: " + s); case Integer i -> System.out.println("Integer with value " + i.getInteger()); default -> System.out.println("Some other type"); } } void typeTester(Shape shape) { // Using previous sealed class example switch (shape) { case Triangle t -> System.out.println("It's a triangle"); case Square s -> System.out.println("It's a square"); case Pentagon p -> System.out.println("It's a pentagon"); } }
  • 60.
    60 Guarded Patterns void shapeTester(Shapeshape) { // Using previous sealed class example switch (shape) { case Triangle t && t.area() > 25 -> System.out.println("It's a big triangle"); case Triangle t -> System.out.println("It's a small triangle"); case Square s -> System.out.println("It's a square"); case Pentagon p -> System.out.println("It's a pentagon"); } } GuardedPattern: PrimaryPattern && ConditionalAndExpression
  • 61.
  • 62.
    62 Removed From TheJDK • JDK 14: CMS Garbage Collector o You should really be using G1 (or Azul Prime) • JDK 15: Nashorn scripting engine o JavaScript from Java? • JDK 17: Experimental AOT and JIT compilers o Didn't shown much appeal • JDK 17: Deprecate the Security Manager for removal o No, it doesn't make Java less secure
  • 63.
    63 Internal JDK APIs •JDK 9 introduced encapsulation of internal JDK APIs o Never intended for general developer use o Too difficult for backwards compatibility - Off by default - Controlled by --illegal-access flag • JDK 16 took this one step further o Default became deny access o Access could still be turned back on • JDK 17 completes strong encapsulation (almost) o The --illegal-access flag now has no effect (just a warning) o Critical APIs (like sun.misc.Unsafe) are still accessible
  • 64.
  • 65.
    65 Azul Platform Core/ Azul Zulu Builds of OpenJDK • Enhanced build of OpenJDK source code o Fully TCK tested o JDK 6, 7, 8, 11, 13 and 15 supported with updates • Wide platform support: o Intel 64-bit Windows, Mac, Linux o Intel 32-bit Windows and Linux • Real drop-in replacement for Oracle JDK o Many enterprise customers o No reports of any compatibility issues
  • 66.
    66 Azul Platform CoreExtended Support • Backporting of bug fixes and security patches from supported OpenJDK release • Azul Zulu Builds of OpenJDK 8 supported until December 2030 • LTS releases have 9 years active + 2 years passive support • JDK 15 is a Medium Term Support release o Bridge to next LTS release (JDK 17) o Supported until 18 months after JDK 17 release
  • 67.
    67 Conclusions • The six-monthrelease cycle is working well • The language is developing to address some developerpain-points • There are some other new features we have not been able to cover o JVM specific things • Use Azul Platform Core, with Azul Zulu builds of OpenJDK, if you want to deploy to production
  • 68.