0% found this document useful (0 votes)
23 views

Modern Java Workshop

Uploaded by

jahangir.infis
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
23 views

Modern Java Workshop

Uploaded by

jahangir.infis
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 50

{

Getting The Most From


Modern Java
Presented by Simon Ritter, Deputy CTO | Azul Systems Inc.
Introduction

Java has changed…


…a lot
• Six-month release cadence
• Seven releases since JDK 9
• More features being delivered faster than ever before

2
Incubator Modules
• Defined by JEP 11
• Non-final APIs and non-final tools
‒ Deliver to developers to solicit feedback
‒ Can result in changes or even removal
‒ First example: HTTP/2 API (Introduced in JDK 9, final in JDK 11)

3
Preview Features
• Defined by JEP 12
• New feature of the Java language, JVM or Java SE APIs
‒ Fully specified, fully implemented but not permanent
‒ Solicit developer real-world use and experience
‒ May lead to becoming a permanent feature in future release
• Must be explicitly enabled
‒ javac --release 14 --enable-preview ...
‒ java --enable-preview ...
• Preview APIs
‒ May be required for a preview language feature
‒ Part of the Java SE API (java or javax namespace)

4
JDK 12
Switch Expressions (Preview)
• Switch construct was a statement
‒ No concept of generating a result that could be assigned
• Rather clunky syntax
‒ Every case statement needs to be separated
‒ Must remember break (default is to fall through)
‒ Scope of local variables is not intuitive

6
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); };

7
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);
};
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);
};
Streams

• New collector, teeing


‒ teeing(Collector, Collector, BiFunction)
• Collect a stream using two collectors
• Use a BiFunction to merge the two collections

Collector 1
Stream Result
BiFunction

Collector 2

10
Streams

// Averaging
Double average = Stream.of(1, 4, 5, 2, 1, 7)
.collect(teeing(summingDouble(i -> i), counting(),
(sum, n) -> sum / n));

11
JDK 13
Text Blocks (Preview)
String webPage = """
<html>
<body>
<p>My web page</p>
incidental white space
</body>
</html>""";
System.out.println(webPage);

$ java WebPage
<html>
<body>
<p>My web page</p>
</body>
</html>
$
Text Blocks (Preview)
String webPage = """
<html>
Intentional indentation
<body>
<p>My web page</p>
</body>
incidental white space </html>
""";
System.out.println(webPage);
$ java WebPage
<html>
<body>
<p>My web page</p>
</body>
</html>
Additional blank line
$
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);
};
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
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;
}
}
18
Records (Preview)

record Point(double x, double y) { }

record Range(int low, int high) {


public Range { // Compact constructor
if (low > high)
throw new IllegalArgumentException("Bad values");
}
}

19
Record Additional Details
• Compact constructor can only throw unchecked exception
‒ Syntax does not allow for specifying a checked exception
• Object methods equals(), hashCode() and toString() can be
overridden
• The base class of all records is java.lang.Record
‒ This is an example of a preview feature Java SE API
‒ Records cannot sub-class (but may implement interfaces)
• Records do not follow the Java bean pattern
‒ x() not getX() in previous example
• Instance fields cannot be added to a record
‒ Static fields can
• Records can be generic
20
Using instanceof

if (obj instanceof String) {


String s = (String)obj;
System.out.println(s.length());
}

21
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());

22
Pattern Matching instanceof (Preview)

if (!(o instanceof String s && s.length() > 3)


return;

System.out.println(s.length());

23
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""";
Helpful NullPointerException
• Who's never had an NullPointerException?

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)

• Enabled with -XX:+ShowCodeDetailsInExceptionMessages


25
JDK 15
Java Inheritance
• A class (or interface) in Java can be sub-classed by any class
‒ Unless it is marked as final

Shape

Triangle Square Pentagon

27
Sealed Classes (JEP 360)
• Preview feature
• Sealed classes allow control over which classes can sub-class a class
‒ Think of final as the ultimate sealed class

• Although called sealed classes, this also applies to interfaces

28
Sealed Classes (JEP 360)
• Uses contextual keywords
‒ New idea replacing restricted identifiers and keywords
‒ sealed, permits and non-sealed
• Classes must all be in the same package or module

public sealed class Shape permits Triangle, Square, Pentagon { ... }

Shape X

Triangle Square Pentagon Circle

29
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 { ... }

30
Contextual Keyword Humour

int non = 2;
int sealed = 1;

var var = non-sealed;

31
Hidden Classes (JEP 371)
• JVM rather than language-level feature
• Classes that cannot be used directly by the bytecodes of other classes
• Several situations where bytecodes generated at runtime
‒ Use of invokedynamic bytecode
‒ Lambdas are a good example
‒ Mostly bound to static class (not for use elsewhere)
‒ Often only used for short time
• Hidden classes can only be accessed via reflection
‒ Primarily intended for framework developers

32
Records (Second Preview)
• Record fields are now (really) final
‒ Cannot be changed via reflection (will throw IllegalAccessException)
• Native methods now explicitly prohibited
‒ Could introduce behaviour dependent on external state

33
Records (Second Preview)
• Local records
‒ Like a local class
‒ Implicitly static

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());
}

34
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 { ... }

35
JDK 16
Pattern Matching instanceof (JEP 394)
• Now final, i.e. part of the Java SE specification
• Two minor changes to previous iterations
‒ Pattern variables are no longer implicitly final
‒ 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 printUpperLeftColoredPoint(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) {
| ^-------------------------^
37
Add UNIX-Domain Socket Channels
• Add UNIX_AF socket channels
‒ Used for IPC on UNIX-based OSs and Windows
• Better security and performance than TCP/IP loopback connections
‒ Behaviour is identical
• No constructor, use factory methods
var unix = UnixDomainSocketAddress.of("/tmp/foo");

38
Streams mapMulti
• Similar to flatMap
‒ Each element on the input stream is mapped to zero or more elements on the output
stream
‒ Difference is that a mapping can be applied at the same time
‒ Uses a BiConsumer

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

39
Vector API (JEP 338)
• Incubator module (not part of the Java SE specification)
• API to express vector computations
‒ Compile at runtime to optimal hardware instructions
‒ Deliver superior performance to equivalent scalar operations

• Ideally, this would not be necessary


‒ Compiler should identify where vector operations can be used

40
Vector API (JEP 338)
void scalarComputation(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++)
c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
}

static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_256;

void vectorComputation(float[] a, float[] b, float[] c) {


for (int i = 0; i < a.length; i += SPECIES.length()) {
var m = SPECIES.indexInRange(i, a.length);
var va = FloatVector.fromArray(SPECIES, a, i, m);
var vb = FloatVector.fromArray(SPECIES, b, i, m);
var vc = va.mul(va).
add(vb.mul(vb)).
neg();
vc.intoArray(c, i, m);
}
}
41
Foreign-Memory Access API (JEP 393)
• Introduced in JDK 14, now third incubator iteration
• API for safe and efficient access to memory outside of the Java heap
• MemorySegment
‒ Models a contiguous area of memory
• MemoryAddress
‒ Models an individual memory address (on or off heap)
• MemoryLayout
‒ Programmatic description of a MemorySegment

try (MemorySegment segment = MemorySegment.allocateNative(100)) {


for (int i = 0; i < 25; i++)
MemoryAccess.setIntAtOffset(segment, i * 4, i);
}
42
Foreign-Memory Access API (JEP 393)
• Example using MemoryLayout and VarHandle
‒ Simpler access of structured data

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);
}
43
Foreign Linker API (JEP 389): Incubator
• Provides statically-typed, pure-Java access to native code
‒ Works in conjunction with the Foreign Memory Access API
‒ Initially targeted at C native code. C++ should follow
• More powerful when combined with Project Panama jextract command

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());
}
44
Warnings for Value-Based Classes
• Part of Project Valhalla, which adds value-types to Java
‒ Introduces the concept of primitive classes
• Primitive wrapper classes (Integer, Float, etc.) designated value-based
‒ Constructors were deprecated in JDK 9
‒ Now marked as for removal
‒ Attempting to synchronize on an instance of a value-based class will issue a warning

45
Strongly Encapsulate JDK Internals By Default
• Encapsulation of JDK internal APIs started in JDK 9
‒ Part of modularity (Project Jigsaw)
• Side effect was the potential to break many applications and frameworks
‒ Spring, etc.
• The big kill switch was included to get round this
‒ --illegal-access
‒ Four options: permit, warn, debug, deny
‒ Until now default has been permit
‒ New default is deny
• Critical internal APIs are still not encapsulated
‒ Including sun.misc.Unsafe

46
Summary
Zulu Enterprise
• Enhanced build of OpenJDK source code
 Fully TCK tested
 JDK 6, 7, 8, 11 and 13
 TLS1.3, Flight Recorder backports
• Wide platform support:
 Intel 64-bit Windows, Mac, Linux
 Intel 32-bit Windows and Linux
• Real drop-in replacement for Oracle JDK
 Many enterprise customers
 No reports of any compatibility issues

48
Conclusions
• The six-month release cycle is working well
• JDK 12 to JDK 16 contains lots of great new features
• Start preparing for JDK 17, the next LTS
‒ Test with JDK 16
• Use Zulu builds of OpenJDK if you want to deploy to production

49
Questions?

You might also like