Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo

1

OpenJDK 17: Get Ready
For the Next LTS Java
Presented by Simon Ritter, Deputy CTO | Azul Systems Inc.

2

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

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

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

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)

6

JDK 12

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
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

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

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

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

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

JDK 13

15

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

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

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

JDK 14

20

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

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

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(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

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

25
Record Default Constructor
record Trex(int x, int y) {
public Trex() { // Default constructor
this(2, 3); // This line must be present
}
}

26

26
Using instanceof
if (obj instanceof 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
• 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

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'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

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

35

JDK 15

36

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

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

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

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

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

JDK 16

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
• 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

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

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

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

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 (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

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

52
Generated Code (No Vector API)
Loop unrolling
no vector instructions

53

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

54
Generated Code (Vector API)
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-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

57

JDK 17

58

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

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

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

61

Compatability
Issues

62

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

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

Summary

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 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

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

68

Questions?

More Related Content

Modern Java Workshop

  • 1. OpenJDK 17: Get Ready For the Next LTS Java Presented by Simon Ritter, Deputy CTO | Azul Systems Inc.
  • 2. 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. 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. 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. 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)
  • 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 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. 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. 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. 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. 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));
  • 15. 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. 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. 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); };
  • 20. 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. 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. 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(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. 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. 25 Record Default Constructor record Trex(int x, int y) { public Trex() { // Default constructor this(2, 3); // This line must be present } }
  • 26. 26 Using instanceof if (obj instanceof 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 • 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. 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'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. 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
  • 36. 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. 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. 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. 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. 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 { ... }
  • 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 • 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. 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. 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. 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. 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 (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. 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. 52 Generated Code (No Vector API) Loop unrolling no vector instructions
  • 53. 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. 54 Generated Code (Vector API) 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-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
  • 58. 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. 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. 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
  • 62. 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. 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
  • 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 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. 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