Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Evolution and Examples of Java Features, from Java 1.7 to Java 22
1. Yann-Gaël Guéhéneuc
(/jan/, he/il)
Work licensed under Creative Commons
BY-NC-SA 4.0 International
New Java
yann-gael.gueheneuc@concordia.ca
Version 0.22.1
2024/03/28
6. 6/360
Documents
JLSs: Java Language Specifications
– What is Java
JSRs: Java Specification Requests
– Parts of the JCP
– New specifications and technologies
– JDK/OpenJDK
JEPs: Java Enhancement Proposals
– Experimental ideas
– Could become JSRs
https://stackoverflow.com/questions/51282326/what-is-the-difference-or-relation-between-jls-jsr-and-jep
12. 12/360
Enums
Special data type
– Declares/defines
variables set to
constants
interface PseudoEnum0 {
int YES = 0;
int NO = 1;
}
interface Interface1 {
public boolean foo();
}
enum RealEnum1 implements Interface1 {
YES {
public boolean foo() {
return true;
}
},
NO {
public boolean foo() {
return false;
}
};
public boolean bar() {
return this.foo();
}
}
13. 13/360
Enums
Based on anonymous classes
System.out.println(RealEnum1.YES.bar());
System.out.println(RealEnum1.NO.bar());
System.out.print("Superclass: ");
System.out.println(RealEnum1.NO.getClass().getSuperclass());
System.out.print("Class: ");
System.out.println(RealEnum1.NO.getClass());
for (final Method method : RealEnum1.NO.getClass().getDeclaredMethods()) {
System.out.print("tMethods: ");
System.out.println(method);
}
14. 14/360
Enums
Based on anonymous classes
System.out.println(RealEnum1.YES.bar());
System.out.println(RealEnum1.NO.bar());
System.out.print("Superclass: ");
System.out.println(RealEnum1.NO.getClass().getSuperclass());
System.out.print("Class: ");
System.out.println(RealEnum1.NO.getClass());
for (final Method method : RealEnum1.NO.getClass().getDeclaredMethods()) {
System.out.print("tMethods: ");
System.out.println(method);
}
true
false
Superclass: class net.ptidej.newjava.enums.RealEnum1
Class: class net.ptidej.newjava.enums.RealEnum1$2
Methods: public boolean net.ptidej.newjava.enums.RealEnum1$2.foo()
15. 15/360
Enums
Enum Simulated Enum
interface Interface1 {
public boolean foo();
}
enum RealEnum1 implements Interface1 {
YES {
public boolean foo() {
return true;
}
},
NO {
public boolean foo() {
return false;
}
};
public boolean bar() {
return this.foo();
}
}
interface Interface1 {
public boolean foo();
}
abstract class SimulatedEnum1 implements Interface1 {
public static final SimulatedEnum1 YES =
new SimulatedEnum1() {
@Override
public boolean foo() {
return true;
}
};
public static final SimulatedEnum1 NO =
new SimulatedEnum1() {
@Override
public boolean foo() {
return false;
}
};
private SimulatedEnum1() {
}
public boolean bar() {
return this.foo();
}
}
16. 16/360
Enums
Enum Simulated Enum
interface Interface1 {
public boolean foo();
}
enum RealEnum1 implements Interface1 {
YES {
public boolean foo() {
return true;
}
},
NO {
public boolean foo() {
return false;
}
};
public boolean bar() {
return this.foo();
}
}
interface Interface1 {
public boolean foo();
}
abstract class SimulatedEnum1 implements Interface1 {
public static final SimulatedEnum1 YES =
new SimulatedEnum1() {
@Override
public boolean foo() {
return true;
}
};
public static final SimulatedEnum1 NO =
new SimulatedEnum1() {
@Override
public boolean foo() {
return false;
}
};
private SimulatedEnum1() {
}
public boolean bar() {
return this.foo();
}
}
Instances of two
anonymous classes
17. 17/360
Enums
Enum Simulated Enum
interface Interface1 {
public boolean foo();
}
enum RealEnum1 implements Interface1 {
YES {
public boolean foo() {
return true;
}
},
NO {
public boolean foo() {
return false;
}
};
public boolean bar() {
return this.foo();
}
}
Why private?
interface Interface1 {
public boolean foo();
}
abstract class SimulatedEnum1 implements Interface1 {
public static final SimulatedEnum1 YES =
new SimulatedEnum1() {
@Override
public boolean foo() {
return true;
}
};
public static final SimulatedEnum1 NO =
new SimulatedEnum1() {
@Override
public boolean foo() {
return false;
}
};
private SimulatedEnum1() {
}
public boolean bar() {
return this.foo();
}
}
Instances of two
anonymous classes
18. 18/360
Enums
More than just syntactic sugar
– Constants are constant expressions
final RealEnum3 v = // ...
switch (v) {
case YES:
System.out.println("YES");
break;
case NO:
System.out.println("NO");
break;
default:
throw // ...
}
final SimulatedEnum3 v1 = // ...
switch (v1) {
case SimulatedEnum3.YES:
System.out.println("YES");
break;
case SimulatedEnum3.NO:
System.out.println("NO");
break;
default:
throw // ...
}
19. 19/360
Enums
More than just syntactic sugar
– Constants are constant expressions
final RealEnum3 v = // ...
switch (v) {
case YES:
System.out.println("YES");
break;
case NO:
System.out.println("NO");
break;
default:
throw // ...
}
final SimulatedEnum3 v1 = // ...
switch (v1) {
case SimulatedEnum3.YES:
System.out.println("YES");
break;
case SimulatedEnum3.NO:
System.out.println("NO");
break;
default:
throw // ...
}
case expressions must be constant expressions
20. 20/360
Enums
No work around the compilation error
– Some constants are not constant expressions
final SimulatedEnum3 v1 = // ...
switch (v1) {
case SimulatedEnum3.YES:
System.out.println("YES");
break;
case SimulatedEnum3.NO:
System.out.println("NO");
break;
default:
throw // ...
}
final int v2 = // ...
switch (v2) {
case SimulatedEnum3.YES.constantID:
System.out.println("YES");
break;
case SimulatedEnum3.NO.constantID:
System.out.println("NO");
break;
default:
throw // ...
}
public final int constantID;
28. 28/360
Underscores in Numeric Literals
int i = 12_34_56;
System.out.println(i);
https://www.geeksforgeeks.org/using-underscore-numeric-literals-java/
32. 32/360
JSR-292: invokedynamic
invokestatic, for class methods
invokevirtual, for instance methods
invokeinterface, for interface methods
invokespecial, for instance initialisation,
superclass, and private methods
36. 36/360
JSR-166: Concurrency Utilities
Concurrency utilities under JSR 166
java.util.concurrent wants to be for
concurrency what java.util.Collections
is for collections
With some JVM support
– Timing
– Atomics
– …
https://gee.cs.oswego.edu/dl/concurrency-interest/jsr166-slides.pdf
45. 45/360
JSR-203: New File I/O Library
Extensive File I/O API
Socket channel API
Asynchronous I/O API
46. 46/360
JSR-203: New File I/O Library
Extensive File I/O API
https://www.baeldung.com/java-nio2-file-visitor
https://www.baeldung.com/java-nio2-file-visitor
public class Example1FileVisitor {
public static void main(final String[] args) throws IOException {
final Path startPath = Paths.get("D:DocumentsTutorials220926 - New Java");
final String fileName = "Example1FileVisitor.java";
final FileVisitorImpl visitor = new FileVisitorImpl(fileName, startPath);
Files.walkFileTree(startPath, visitor);
}
}
47. 47/360
JSR-203: New File I/O Library
https://www.baeldung.com/java-nio2-file-visitor
class FileVisitorImpl implements FileVisitor<Path> {
private final String fileName;
private final Path startPath;
public FileVisitorImpl(final String aFileName, final Path aStartPath) {
this.fileName = aFileName;
this.startPath = aStartPath;
}
@Override
public FileVisitResult preVisitDirectory(final Path aPath, final BasicFileAttributes someAttributes) {
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(final Path aPath, final BasicFileAttributes someAttributes) {
final String fileName = aPath.getFileName().toString();
if (fileName.equals(this.fileName)) {
return FileVisitResult.TERMINATE;
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(final Path aPath, final IOException anIOException) {
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(final Path aPath, final IOException anIOException) {
try {
if (Files.isSameFile(aPath, this.startPath)) {
return FileVisitResult.TERMINATE;
}
} catch (final IOException e) {
e.printStackTrace();
}
return FileVisitResult.CONTINUE;
}
}
48. 48/360
JSR-203: New File I/O Library
Socket channel API – Client
public static void client() throws IOException {
final ServerSocketChannel serverSocket = ServerSocketChannel.open();
serverSocket.socket().bind(new InetSocketAddress(9000));
final SocketChannel client = serverSocket.accept();
System.out.println("Connection set: " + client.getRemoteAddress());
final Path path = Paths.get("D:DocumentsTutorials220926 - New JavaReceivedFile.txt");
final FileChannel fileChannel = FileChannel.open(
path,
EnumSet.of(StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING,
StandardOpenOption.WRITE));
final ByteBuffer buffer = ByteBuffer.allocate(1024);
while (client.read(buffer) > 0) {
buffer.flip();
fileChannel.write(buffer);
buffer.clear();
}
fileChannel.close();
System.out.println("File received");
client.close();
}
https://www.tutorialspoint.com/java_nio/java_nio_socket_channel.htm
49. 49/360
JSR-203: New File I/O Library
Socket channel API – Server
https://www.tutorialspoint.com/java_nio/java_nio_socket_channel.htm
public static void server() throws IOException {
final SocketChannel server = SocketChannel.open();
final SocketAddress socketAddr = new InetSocketAddress("localhost", 9000);
server.connect(socketAddr);
final Path path = Paths.get("D:DocumentsTutorials220926 - New JavaPatterns.txt");
final FileChannel fileChannel = FileChannel.open(path);
final ByteBuffer buffer = ByteBuffer.allocate(1024);
while (fileChannel.read(buffer) > 0) {
buffer.flip();
server.write(buffer);
buffer.clear();
}
fileChannel.close();
System.out.println("File sent");
server.close();
}
50. 50/360
JSR-203: New File I/O Library
Socket channel API – Main
public static void main(final String[] args) {
final Runnable runnableClient = new Runnable() {
public void run() {
try {
Example2SocketChannel.client();
} catch (final IOException e) {
}
}
};
final Runnable runnableServer = new Runnable() {
public void run() {
try {
Example2SocketChannel.server();
} catch (final IOException e) {
}
}
};
final ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(runnableClient);
executor.execute(runnableServer);
}
https://www.tutorialspoint.com/java_nio/java_nio_socket_channel.htm
51. 51/360
JSR-203: New File I/O Library
Asynchronous I/O API
“The asynchronous channel APIs were
introduced into the existing
java.nio.channels package […] by
prefixing […] with Asynchronous”
52. 52/360
Translucent and Shaped Windows
Improves Java Swing
Allow new, nicer themes
https://ateraimemo.com/Swing/TranslucentFrame.html
Window.setShape(Shape s)
Window.setOpacity(float f)
53. 53/360
Network Protocols
Network protocols
– Stream Control
Transport Protocol
(SCTP)
– Sockets Direct
Protocol (SDP)
In packages
– com.sun.nio.sctp
– com.sun.sdp
https://www.oracle.com/technical-resources/articles/javase/sctp.html
final SctpServerChannel ssc =
SctpServerChannel.open();
final InetSocketAddress serverAddr = // ...
ssc.bind(serverAddr);
while (true) {
final SctpChannel sc = ssc.accept();
final Date today = new Date();
cbuf.put(USformatter.format(today)).flip();
encoder.encode(cbuf, buf, true);
buf.flip();
messageInfo.streamNumber(FUS_STREAM);
sc.send(buf, messageInfo);
buf.clear();
cbuf.clear();
cbuf.put(FRformatter.format(today)).flip();
encoder.encode(cbuf, buf, true);
buf.flip();
messageInfo.streamNumber(FR_STREAM);
sc.send(buf, messageInfo);
buf.clear();
cbuf.clear();
// ...
54. 54/360
Updates to XML and Unicode
New system property named
org.jcp.xml.dsig.secureValidation
New XML Processing Limits
Regular Expression pattern matching
supports Unicode 6.0.0
– Major version of the Unicode Standard
57. 57/360
default, static Interface Methods
public interface IA {
int foo();
default int bar() {
return 42;
}
}
public static void main(final String[] args) {
final IA anIA = new IA() {
public int foo() {
return 0;
}
};
System.out.println(anIA.foo());
System.out.println(anIA.bar());
final IA anotherIA = new IA() {
public int foo() {
return IA.super.bar();
}
public int bar() {
return 0;
}
};
System.out.println(anotherIA.foo());
System.out.println(anotherIA.bar());
}
58. 58/360
default, static Interface Methods
public interface IA {
int foo();
default int bar() {
return 42;
}
}
public static void main(final String[] args) {
final IA anIA = new IA() {
public int foo() {
return 0;
}
};
System.out.println(anIA.foo());
System.out.println(anIA.bar());
final IA anotherIA = new IA() {
public int foo() {
return IA.super.bar();
}
public int bar() {
return 0;
}
};
System.out.println(anotherIA.foo());
System.out.println(anotherIA.bar());
}
0
42
42
0
59. 59/360
default, static Interface Methods
https://stackoverflow.c
om/questions/512877/
why-cant-i-define-a-
static-method-in-a-
java-interface
public interface IA {
int foo();
static int bar() {
return 42;
}
}
public class A {
int foo() {
return 0;
}
static int bar() {
return 42;
}
}
public static void main(final String[] args) {
final IA anIA = new IA() {
public int foo() {
return 0;
}
};
System.out.println(anIA.foo());
System.out.println(anIA.bar());
final A anA = new A();
System.out.println(anA.foo());
System.out.println(anA.bar());
}
60. 60/360
default, static Interface Methods
https://stackoverflow.c
om/questions/512877/
why-cant-i-define-a-
static-method-in-a-
java-interface
public interface IA {
int foo();
static int bar() {
return 42;
}
}
public class A {
int foo() {
return 0;
}
static int bar() {
return 42;
}
}
public static void main(final String[] args) {
final IA anIA = new IA() {
public int foo() {
return 0;
}
};
System.out.println(anIA.foo());
System.out.println(anIA.bar());
final A anA = new A();
System.out.println(anA.foo());
System.out.println(anA.bar());
}
61. 61/360
default, static Interface Methods
https://stackoverflow.c
om/questions/512877/
why-cant-i-define-a-
static-method-in-a-
java-interface
public interface IA {
int foo();
static int bar() {
return 42;
}
}
public class A {
int foo() {
return 0;
}
static int bar() {
return 42;
}
}
public static void main(final String[] args) {
final IA anIA = new IA() {
public int foo() {
return 0;
}
};
System.out.println(anIA.foo());
System.out.println(anIA.bar());
final A anA = new A();
System.out.println(anA.foo());
System.out.println(anA.bar());
}
System.out.println(IA.bar());
62. 62/360
JSR-335, JEP-126: λ Expressions
λ Expressions
interface Applicable<T, R> {
public R apply(final T aParameter);
}
public static void main(final String[] args) {
final Applicable<String, Integer> strlen = new Applicable<>() {
@Override
public Integer apply(final String aParameter) {
return aParameter.length();
}
};
System.out.println(strlen.apply("Hello, World!"));
}
https://jenkov.com/tutorials/java-functional-programming/functional-interfaces.html
63. 63/360
JSR-335, JEP-126: λ Expressions
interface Applicable<T, R> {
public R apply(final T aParameter);
}
public static void main(final String[] args) {
final Applicable<String, Integer> strlen = new Applicable<>() {
@Override
public Integer apply(final String aParameter) {
return aParameter.length();
}
};
System.out.println(strlen.apply("Hello, World!"));
}
64. 64/360
JSR-335, JEP-126: λ Expressions
Lots of boilerplate code
Difficult to understand
Not common in the libraries
interface Applicable<T, R> {
public R apply(final T aParameter);
}
public static void main(final String[] args) {
final Applicable<String, Integer> strlen = new Applicable<>() {
@Override
public Integer apply(final String aParameter) {
return aParameter.length();
}
};
System.out.println(strlen.apply("Hello, World!"));
}
65. 65/360
JSR-335, JEP-126: λ Expressions
Solution
– Simple syntactic sugar
– Set of functional interfaces
– Libraries using these interfaces
66. 66/360
JSR-335, JEP-126: λ Expressions
Solution
– Simple syntactic sugar
– Set of functional interfaces
– Libraries using these interfaces
67. 67/360
JSR-335, JEP-126: λ Expressions
Solution
– Simple syntactic sugar
– Set of functional interfaces
– Libraries using these interfaces
interface Applicable<T, R> {
public R apply(final T aParameter);
}
public static void main(final String[] args) {
final Applicable<String, Integer> strlen = (paramter) -> paramter.length();
System.out.println(strlen.apply("Hello, World!"));
}
68. 68/360
JSR-335, JEP-126: λ Expressions
Solution
– Simple syntactic sugar
– Set of functional interfaces
– Libraries using these interfaces
interface Applicable<T, R> {
public R apply(final T aParameter);
}
public static void main(final String[] args) {
final Applicable<String, Integer> strlen = (paramter) -> paramter.length();
System.out.println(strlen.apply("Hello, World!"));
}
public static void main(final String[] args) {
final Applicable<String, Integer> strlen = String::length;
System.out.println(strlen.apply("Hello, World!"));
}
69. 69/360
JSR-335, JEP-126: λ Expressions
Solution
– Simple syntactic sugar
– Set of functional interfaces
– Libraries using these interfaces
http://blog.orfjackal.net/2014/07/java-8-functional-interface-naming-guide.html
70. 70/360
JSR-335, JEP-126: λ Expressions
Solution
– Simple syntactic sugar
– Set of functional interfaces
– Libraries using these interfaces
http://blog.orfjackal.net/2014/07/java-8-functional-interface-naming-guide.html
71. 71/360
JSR-335, JEP-126: λ Expressions
Solution
– Simple syntactic sugar
– Set of functional interfaces
– Libraries using these interfaces
https://blogs.oracle.com/javamagazine/post/functional-programming-in-java-part-1-lists-lambdas-and-method-references
72. 72/360
JSR-335, JEP-126: λ Expressions
Solution
– Simple syntactic sugar
– Set of functional interfaces
– Libraries using these interfaces
https://blogs.oracle.com/javamagazine/post/functional-programming-in-java-part-1-lists-lambdas-and-method-references
final List<String> friends = Arrays.asList("Rick Deckard", "Roy Batty", "Harry
Bryant", "Hannibal Chew", "Gaff", "Holden", "Leon Kowalski", "Taffey Lewis",
"Pris", "Rachael", "J.F. Sebastian", "Dr. Eldon Tyrell", "Zhora", "Hodge",
"Mary");
for (int i = 0; i < friends.size(); i++) {
System.out.println(friends.get(i));
}
for (String name : friends) {
System.out.println(name);
}
friends.forEach(new Consumer<String>() {
public void accept(final String aName) { System.out.println(aName); }});
friends.forEach((final String name) -> System.out.println(name));
friends.forEach((name) -> System.out.println(name));
friends.forEach(name -> System.out.println(name));
friends.forEach(System.out::println);
friends.stream().map(String::toUpperCase).forEach(
name -> System.out.print(name + " "));
System.out.println();
final List<String> namesStartingWithN = friends.stream().
filter(name -> name.startsWith("R")).collect(Collectors.toList());
System.out.println(namesStartingWithN);
73. 73/360
JSR-335, JEP-126: λ Expressions
But code duplication!
https://blogs.oracle.com/javamagazine/post/functional-programming-
in-java-part-2-lambda-reuse-lexical-scoping-and-closures-and-reduce
output = friends1.stream().filter(name -> name.startsWith("R")).collect(Collectors.toList());
System.out.println(output);
output = friends2.stream().filter(name -> name.startsWith("R")).collect(Collectors.toList());
System.out.println(output);
final Predicate<String> predicate = name -> name.startsWith("R");
output = friends1.stream().filter(predicate).collect(Collectors.toList());
System.out.println(output);
output = friends2.stream().filter(predicate).collect(Collectors.toList());
System.out.println(output);
vs.
74. 74/360
JSR-335, JEP-126: λ Expressions
But code duplication!
https://blogs.oracle.com/javamagazine/post/functional-programming-
in-java-part-2-lambda-reuse-lexical-scoping-and-closures-and-reduce
// Lexical scoping and closure
output = friends1.stream().filter(checkIfStartsWith("R")).collect(Collectors.toList());
System.out.println(output);
output = friends2.stream().filter(checkIfStartsWith("P")).collect(Collectors.toList());
System.out.println(output);
// Narrower lexical scoping
final Function<String, Predicate<String>> startsWithLetter = letter -> (name ->
name.startsWith(letter));
output = friends1.stream().filter(startsWithLetter.apply("R")).collect(Collectors.toList());
System.out.println(output);
output = friends2.stream().filter(startsWithLetter.apply("P")).collect(Collectors.toList());
System.out.println(output);
vs.
75. 75/360
JSR-335, JEP-126: λ Expressions
But code duplication!
https://blogs.oracle.com/javamagazine/post/functional-programming-
in-java-part-2-lambda-reuse-lexical-scoping-and-closures-and-reduce
// Lexical scoping and closure
output = friends1.stream().filter(checkIfStartsWith("R")).collect(Collectors.toList());
System.out.println(output);
output = friends2.stream().filter(checkIfStartsWith("P")).collect(Collectors.toList());
System.out.println(output);
// Narrower lexical scoping
final Function<String, Predicate<String>> startsWithLetter = letter -> (name ->
name.startsWith(letter));
output = friends1.stream().filter(startsWithLetter("R")).collect(Collectors.toList());
System.out.println(output);
output = friends2.stream().filter(startsWithLetter("P")).collect(Collectors.toList());
System.out.println(output);
vs.
76. 76/360
JSR-335, JEP-126: λ Expressions
But code duplication!
https://forum.devtalk.com/t/functional-programming-in-java-second-
edition-p-35-refactoring-to-narrow-the-scope-code/105447
// Lexical scoping and closure
output = friends1.stream().filter(checkIfStartsWith("R")).collect(Collectors.toList());
System.out.println(output);
output = friends2.stream().filter(checkIfStartsWith("P")).collect(Collectors.toList());
System.out.println(output);
// Narrower lexical scoping
final Function<String, Predicate<String>> startsWithLetter = letter -> (name ->
name.startsWith(letter));
output = friends1.stream().filter(startsWithLetter("R")).collect(Collectors.toList());
System.out.println(output);
output = friends2.stream().filter(startsWithLetter("P")).collect(Collectors.toList());
System.out.println(output);
vs.
77. 77/360
JSR-308, JEP-104: Type Annotations
Allow pluggable type systems
Help enforce stronger typing
public class Example1 {
public static void main(final String[] args) {
final String aString = null;
final String anotherString = aString;
System.out.println(anotherString);
}
}
78. 78/360
JSR-308, JEP-104: Type Annotations
Allow pluggable type systems
Help enforce stronger typing
public class Example1 {
public static void main(final String[] args) {
final String aString = null;
final String anotherString = aString;
System.out.println(anotherString);
}
}
public class Example1 {
public static void main(final String[] args) {
final String aString = null;
final @NonNull String anotherString = aString;
System.out.println(anotherString);
}
}
79. 79/360
JSR-308, JEP-104: Type Annotations
Allow pluggable type systems
Help enforce stronger typing
public class Example1 {
public static void main(final String[] args) {
final String aString = null;
final String anotherString = aString;
System.out.println(anotherString);
}
}
public class Example1 {
public static void main(final String[] args) {
final String aString = null;
final @NonNull String anotherString = aString;
System.out.println(anotherString);
}
}
Null type mismatch: required
'@NonNull String' but the
provided value is null
80. 80/360
JSR-308, JEP-104: Type Annotations
Allow pluggable type systems
Help enforce stronger typing
public class Example1 {
public static void main(final String[] args) {
final String aString = null;
final String anotherString = aString;
System.out.println(anotherString);
}
}
public class Example1 {
public static void main(final String[] args) {
final String aString = null;
final @NonNull String anotherString = aString;
System.out.println(anotherString);
}
}
public class Example1 {
public static void main(final String[] args) {
final String aString = "";
final @NonNull String anotherString = aString;
System.out.println(anotherString);
}
}
Null type mismatch: required
'@NonNull String' but the
provided value is null
81. 81/360
JSR-308, JEP-104: Type Annotations
class A {
String getString() {
return null;
}
}
public class Example2 {
public static void foo1() {
final A a = new A();
final String aString = a.getString();
final @NonNull String anotherString = aString;
System.out.println(anotherString);
}
public static void foo2() {
final A a = new A();
final String aString = a.getString();
if (aString != null) {
final @NonNull String anotherString = aString;
System.out.println(anotherString);
}
}
}
82. 82/360
JSR-308, JEP-104: Type Annotations
class A {
String getString() {
return null;
}
}
public class Example2 {
public static void foo1() {
final A a = new A();
final String aString = a.getString();
final @NonNull String anotherString = aString;
System.out.println(anotherString);
}
public static void foo2() {
final A a = new A();
final String aString = a.getString();
if (aString != null) {
final @NonNull String anotherString = aString;
System.out.println(anotherString);
}
}
}
Null type safety […] needs
unchecked conversion to
conform to '@NonNull String'
83. 83/360
JSR-308, JEP-104: Type Annotations
“The Checker Framework includes compiler
plug-ins ("checkers") that find bugs or verify
their absence. It also permits you to write
your own compiler plug-ins.”
– https://checkerframework.org/tutorial/
84. 84/360
Unsigned Integer Arithmetic
Comparison
Division/Modulo
Parsing
Formatting
https://www.baeldung.com/java-unsigned-arithmetic
public class Example1 {
public static void main(String[] args) {
final int positive = Integer.MAX_VALUE;
final int negative = Integer.MIN_VALUE;
final int signedComparison = Integer.compare(positive, negative);
if (signedComparison > 0) {
System.out.println("Positive > negative (signed comparison)");
}
final int unsignedComparison = Integer.compareUnsigned(positive, negative);
if (unsignedComparison < 0) {
System.out.println("Positive NOT > negative (unsigned comparison)");
}
}
}
85. 85/360
JEP-120: Repeating Annotations
“Annotations, a form of metadata, provide
data about a program that is not part of the
program [and] have no direct effect on the
operation of the code they annotate.”
https://docs.oracle.com/javase/tutorial/java/annotations/
86. 86/360
JEP-120: Repeating Annotations
“Annotations, a form of metadata, provide
data about a program that is not part of the
program [and] have no direct effect on the
operation of the code they annotate.”
https://docs.oracle.com/javase/tutorial/java/annotations/
94. 94/360
JEP-178: Statically-linked JNI
Libraries
Native programs that embed the JRE
Java programs running in environments
without shared libraries
Enable developers to package a Java run-
time, native code, and Java code together
into a single binary
95. 95/360
JEP-122: Permanent Generation
Removal
“Automatic garbage
collection is [..]
identifying which
objects are in use and
[…] deleting the
unused objects.”
Remove Permanent
Generation
– No more size tuning
https://openjdk.org/jeps/122
97. 97/360
JEP-174: Nashorn JS Engine
Successor of Mozilla’s Rhino
100% in ECMAScript v5.1 test suite
Java 8: Introduced
Java 11: Deprecated
Java 15: Removed
98. 98/360
JEP-174: Nashorn JS Engine
https://github.com/openjdk/nashorn
https://www.baeldung.com/java-nashorn
final ScriptEngine engine = new ScriptEngineManager().getEngineByName("Nashorn");
final Bindings bindings = engine.createBindings();
bindings.put("name", "Nashorn");
result = engine.eval("var greeting = 'hello world' + name;" + "print(greeting);" + "greeting");
System.out.println(result);
final Invocable invocable = (Invocable) engine;
engine.eval("function composeGreeting(name) {" + "return 'Hello ' + name" + "}");
result = invocable.invokeFunction("composeGreeting", "Nashorn");
System.out.println(result);
result = engine.eval("var HashMap = Java.type('java.util.HashMap’);"
+ "var map = new HashMap();"
+ "map.put('hello', 'world');" + "map");
System.out.println(result);
99. 99/360
JSR-310, JEP-150: Date, Time API
Need to manipulate dates and times
Disparate APIs, missing features
– Set time to midnight for a date without a time
Complete terminology
Complete, cohesive implementation
– java.time.*
101. 101/360
JEP-153: JavaFX Applications
Three “types” of programs
– Class files
– JAR files
– JavaFX
Enhance the java command-line to launch
JavaFX programs
104. 104/360
Private Interface Methods
public interface IA {
int foo();
default int bar() {
return this.bar1();
}
private int bar1() {
return 42;
}
}
public static void main(final String[] args) {
final IA anIA = new IA() {
public int foo() {
return 0;
}
};
System.out.println(anIA.foo());
System.out.println(anIA.bar());
final IA anotherIA = new IA() {
public int foo() {
return IA.super.bar1();
}
public int bar() {
return 0;
}
};
System.out.println(anotherIA.foo());
System.out.println(anotherIA.bar());
}
105. 105/360
Private Interface Methods
public interface IA {
int foo();
default int bar() {
return this.bar1();
}
private int bar1() {
return 42;
}
}
public static void main(final String[] args) {
final IA anIA = new IA() {
public int foo() {
return 0;
}
};
System.out.println(anIA.foo());
System.out.println(anIA.bar());
final IA anotherIA = new IA() {
public int foo() {
return IA.super.bar1();
}
public int bar() {
return 0;
}
};
System.out.println(anotherIA.foo());
System.out.println(anotherIA.bar());
}
0
42
42
0
106. 106/360
JSR-376: Modularization
JSR-376: Java Platform Module System,
part of Project Jigsaw
– Ease library construction, maintenance
– Security, maintainability of Java (and JDK)
– Allow scaling down programs for small devices
– Improve program compilation and loading times
https://openjdk.org/projects/jigsaw/
107. 107/360
JSR-376: Modularization
JEP-200: The Modular JDK
JEP-201: Modular Source Code
JEP-220: Modular Run-time Images
JEP-260: Encapsulate Most Internal APIs
JEP-261: Module System
JEP-282: jlink: The Java Linker
JSR 376: Java Platform Module System
108. 108/360
JSR-376: Modularization
Classpath / JARs Hell
Version conflicts
Large Monolithic JDK
Security Problems
https://www.geeksforgeeks.org/jpms-java-platform-module-system/
109. 109/360
JSR-376: Modularization
Classpath / JARs Hell
Version conflicts
– Cf. DLL Hell, no versions, one directory
– One, long list of JAR files
• Run-time missing dependencies
• Order of declaration (shadowing)
Large Monolithic JDK
Security Problems
https://www.geeksforgeeks.org/jpms-java-platform-module-system/
110. 110/360
JSR-376: Modularization
Classpath / JARs Hell
Version conflicts
Large Monolithic JDK
– E.g., in Java v1.4.2, RT.jar is 21.8 MB (!)
Security Problems
https://www.geeksforgeeks.org/jpms-java-platform-module-system/
111. 111/360
JSR-376: Modularization
Classpath / JARs Hell
Version conflicts
Large Monolithic JDK
Security Problems
– Implementation classes must be public
– Cannot control access to these classes
– padl.kernel vs. padl.kernel.impl
https://www.geeksforgeeks.org/jpms-java-platform-module-system/
112. 112/360
JSR-376: Modularization
A module is a “package of packages”
– With one module descriptor
– With own resources (data)
A module descriptor
– Domain Specific Language
– exports, module, open, opens, provides,
requires, to, transitive, uses, and with
113. 113/360
JSR-376: Modularization
Raoul-Gabriel Urma, Mario Fusco, Alan Mycroft ; Modern Java in Action ; Manning, 2018 (Chapter 14)
module com.example.foo {
requires transitive com.example.foo.network;
requires static com.example.foo.http;
requires java.logging;
exports com.example.foo.bar;
exports com.example.foo.internal to
com.example.foo.probe;
opens com.example.foo.quux;
opens com.example.foo.internal to
com.example.foo.network,
com.example.foo.probe;
uses com.example.foo.spi.Intf;
provides com.example.foo.spi.Data with
com.example.foo.Impl;
}
114. 114/360
JSR-376: Modularization
Raoul-Gabriel Urma, Mario Fusco, Alan Mycroft ; Modern Java in Action ; Manning, 2018 (Chapter 14)
module com.example.foo {
requires transitive com.example.foo.network;
requires static com.example.foo.http;
requires java.logging;
exports com.example.foo.bar;
exports com.example.foo.internal to
com.example.foo.probe;
opens com.example.foo.quux;
opens com.example.foo.internal to
com.example.foo.network,
com.example.foo.probe;
uses com.example.foo.spi.Intf;
provides com.example.foo.spi.Data with
com.example.foo.Impl;
}
115. 115/360
JSR-376: Modularization
Declaration of module
com.example.foo
Dependencies on
three other modules
– transitive: client
modules also can
access that module
– static: at compile-time,
option at run-time
module com.example.foo {
requires transitive com.example.foo.network;
requires static com.example.foo.http;
requires java.logging;
exports com.example.foo.bar;
exports com.example.foo.internal to
com.example.foo.probe;
opens com.example.foo.quux;
opens com.example.foo.internal to
com.example.foo.network,
com.example.foo.probe;
uses com.example.foo.spi.Intf;
provides com.example.foo.spi.Data with
com.example.foo.Impl;
}
116. 116/360
JSR-376: Modularization
(Qualified) exports to
other, client modules
– Public types accessible
to all client modules
– Or only to types in
com.example.foo.probe
module com.example.foo {
requires transitive com.example.foo.network;
requires static com.example.foo.http;
requires java.logging;
exports com.example.foo.bar;
exports com.example.foo.internal to
com.example.foo.probe;
opens com.example.foo.quux;
opens com.example.foo.internal to
com.example.foo.network,
com.example.foo.probe;
uses com.example.foo.spi.Intf;
provides com.example.foo.spi.Data with
com.example.foo.Impl;
}
117. 117/360
JSR-376: Modularization
(Qualified) opening to
other, client modules
at run-time only
– Public types accessible
to all client modules
– Or only to types in com.
example.foo.network or
com.example.foo.probe
– Allows introspection
module com.example.foo {
requires transitive com.example.foo.network;
requires static com.example.foo.http;
requires java.logging;
exports com.example.foo.bar;
exports com.example.foo.internal to
com.example.foo.probe;
opens com.example.foo.quux;
opens com.example.foo.internal to
com.example.foo.network,
com.example.foo.probe;
uses com.example.foo.spi.Intf;
provides com.example.foo.spi.Data with
com.example.foo.Impl;
}
118. 118/360
module com.example.foo {
requires transitive com.example.foo.network;
requires static com.example.foo.http;
requires java.logging;
exports com.example.foo.bar;
exports com.example.foo.internal to
com.example.foo.probe;
opens com.example.foo.quux;
opens com.example.foo.internal to
com.example.foo.network,
com.example.foo.probe;
uses com.example.foo.spi.Intf;
provides com.example.foo.spi.Data with
com.example.foo.Impl;
}
JSR-376: Modularization
Service consumer
– Interface/abstract class
com.example.foo.spi.Intf
Service provider
– Interface/abstract class
com.example.foo.spi.Data
– With concrete class
com.example.foo.Impl
119. 119/360
JSR-376: Modularization
modularisation.Client
– Can access any public
type at compile-time
and at run-time
– Can access some
protected/private
data with introspection
internal.Client
– Cannot access
HiddenImplementation
120. 120/360
JSR-376: Modularization
modularisation.Client
– Can access any public
type at compile-time
and at run-time
– Can access some
protected/private
data with introspection
internal.Client
– Cannot access
HiddenImplementation
Package-protected
Class (not public!)
121. 121/360
JSR-376: Modularization
final Interface aki = new Implementation();
aki.foo();
System.out.println("Call on public implementation: ");
final Class<? extends Interface> implementation1 = Class
.forName(“....impl.Implementation").asSubclass(Interface.class);
final Interface aki1 = implementation1.getDeclaredConstructor().newInstance();
final Method[] methods1 = implementation1.getDeclaredMethods();
for (final Method method : methods1) {
try {
method.setAccessible(true);
method.invoke(aki1, new Object[0]);
} catch (final RuntimeException e) {
System.out.println(e.getMessage());
}
}
final Class<? extends Interface> implementation2 = Class
.forName(“....impl.HiddenImplementation").asSubclass(Interface.class);
final Interface aki2 = implementation2.getDeclaredConstructor().newInstance();
final Method[] methods2 = implementation2.getDeclaredMethods();
for (final Method method : methods2) {
// Same code
122. 122/360
JSR-376: Modularization
The client code has access to the fields and
methods in all public types, even if private
Direct call: Implementation.bar()
Call on public implementation:
bar: Implementation.bar()
foo: Implementation.bar()
Call on hidden implementation:
Exception in thread "main" java.lang.IllegalAccessException: class
net.ptidej.modularisation.Client cannot access a member of class
net.ptidej.modularisation.kernel.impl.HiddenImplementation with package
access
...
123. 123/360
JSR-376: Modularization
The client code has access to the fields and
methods in all public types, even if private
Direct call: Implementation.bar()
Call on public implementation:
bar: Implementation.bar()
foo: Implementation.bar()
Call on hidden implementation:
Exception in thread "main" java.lang.IllegalAccessException: class
net.ptidej.modularisation.Client cannot access a member of class
net.ptidej.modularisation.kernel.impl.HiddenImplementation with package
access
...
Including the
private method
125. 125/360
JSR-376: Modularization
Client (not a module)
Client (module)
Direct call: Implementation.bar()
Call on public implementation:
bar: Implementation.bar()
foo: Implementation.bar()
Call on hidden implementation:
Exception in thread "main" java.lang.IllegalAccessException: class net.ptidej.modularisation.Client
cannot access a member of class net.ptidej.modularisation.kernel.impl.HiddenImplementation with
package access
Direct call: Implementation.bar()
Call on public implementation:
foo: Implementation.bar()
bar: Unable to make private void net.ptidej.modularisation.kernel.impl.Implementation.bar()
accessible: module ModularizationWithModulesLibrary1 does not "opens
net.ptidej.modularisation.kernel.impl" to module ModularizationWithModulesClient1
Call on hidden implementation:
Exception in thread "main" java.lang.IllegalAccessException: class net.ptidej.modularisation.Client
(in module ModularizationWithModulesClient1) cannot access a member of class
net.ptidej.modularisation.kernel.impl.HiddenImplementation (in module
ModularizationWithModulesLibrary1) with package access
126. 126/360
JSR-376: Modularization
Client (not a module)
Client (module)
Direct call: Implementation.bar()
Call on public implementation:
bar: Implementation.bar()
foo: Implementation.bar()
Call on hidden implementation:
Exception in thread "main" java.lang.IllegalAccessException: class net.ptidej.modularisation.Client
cannot access a member of class net.ptidej.modularisation.kernel.impl.HiddenImplementation with
package access
Direct call: Implementation.bar()
Call on public implementation:
foo: Implementation.bar()
bar: Unable to make private void net.ptidej.modularisation.kernel.impl.Implementation.bar()
accessible: module ModularizationWithModulesLibrary1 does not "opens
net.ptidej.modularisation.kernel.impl" to module ModularizationWithModulesClient1
Call on hidden implementation:
Exception in thread "main" java.lang.IllegalAccessException: class net.ptidej.modularisation.Client
(in module ModularizationWithModulesClient1) cannot access a member of class
net.ptidej.modularisation.kernel.impl.HiddenImplementation (in module
ModularizationWithModulesLibrary1) with package access
Non-module can still
access private methods
127. 127/360
JSR-376: Modularization
Client (not a module)
Client (module)
Direct call: Implementation.bar()
Call on public implementation:
bar: Implementation.bar()
foo: Implementation.bar()
Call on hidden implementation:
Exception in thread "main" java.lang.IllegalAccessException: class net.ptidej.modularisation.Client
cannot access a member of class net.ptidej.modularisation.kernel.impl.HiddenImplementation with
package access
Direct call: Implementation.bar()
Call on public implementation:
foo: Implementation.bar()
bar: Unable to make private void net.ptidej.modularisation.kernel.impl.Implementation.bar()
accessible: module ModularizationWithModulesLibrary1 does not "opens
net.ptidej.modularisation.kernel.impl" to module ModularizationWithModulesClient1
Call on hidden implementation:
Exception in thread "main" java.lang.IllegalAccessException: class net.ptidej.modularisation.Client
(in module ModularizationWithModulesClient1) cannot access a member of class
net.ptidej.modularisation.kernel.impl.HiddenImplementation (in module
ModularizationWithModulesLibrary1) with package access
Non-module can still
access private methods
Modules cannot access
private/package data
129. 129/360
JSR-376: Modularization
Client implementation
Client output
Implementation.bar()
Call on public implementation:
Exception in thread "main" java.lang.IllegalAccessException: class net.ptidej.modularisation.Client
(in module ModularizationWithModulesClient2) cannot access class
net.ptidej.modularisation.kernel.impl.Implementation (in module ModularizationWithModulesLibrary2)
because module ModularizationWithModulesLibrary2 does not export
net.ptidej.modularisation.kernel.impl to module ModularizationWithModulesClient2
final ServiceLoader<Interface> providers = ServiceLoader.load(Interface.class);
final Interface aki = providers.findFirst().orElse(null);
aki.foo();
130. 130/360
JSR-376: Modularization
Client implementation
Client output
Implementation.bar()
Call on public implementation:
Exception in thread "main" java.lang.IllegalAccessException: class net.ptidej.modularisation.Client
(in module ModularizationWithModulesClient2) cannot access class
net.ptidej.modularisation.kernel.impl.Implementation (in module ModularizationWithModulesLibrary2)
because module ModularizationWithModulesLibrary2 does not export
net.ptidej.modularisation.kernel.impl to module ModularizationWithModulesClient2
No access to data not
exported/provided,
even if public!
final ServiceLoader<Interface> providers = ServiceLoader.load(Interface.class);
final Interface aki = providers.findFirst().orElse(null);
aki.foo();
134. 134/360
JSR-376: Modularization
Relation to OSGi
– Open Service Gateway Initiative
• From 05/2000, latest 12/2020
– Eclipse Foundation open-source project
– Framework for developing and deploying
• Modular programs and libraries
• IoT and other constrained devices
https://www.techtarget.com/searchnetworking/definition/OSGi
135. 135/360
JSR-376: Modularization
OSGi (Bundles)
Several class loaders
– Cannot be used for the JDK
– Allow “duplicate” packages
– Allow multiple versions
Visibility
JPMS (Modules)
One class loader
– Can be used in the JDK
– Disallow same packages
– No versioning
Accessibility
https://www.infoq.com/articles/java9-osgi-future-modularity/, https://www.infoq.com/articles/java9-osgi-future-modularity-
part-2/, https://www.baeldung.com/java-illegal-reflective-access, https://en.wikipedia.org/wiki/OSGi
136. 136/360
JSR-376: Modularization
OSGi (Bundles)
“[B]uild dependencies and
runtime dependencies can
and often do differ”
JPMS (Modules)
“[T]he module system
should […] work [same] at
compile time, run time…”
Export-Package: org.example.foo;
version=1.0.1, org.example.bar;
version=2.1.0
Import-Package: org.example.foo;
version='[1,2)', org.example.bar;
version='[2.0,2.1)'
module A {
exports org.example.foo;
exports org.example.bar;
}
module B {
require A;
}
https://www.infoq.com/articles/java9-osgi-future-modularity/, https://www.infoq.com/articles/java9-osgi-future-modularity-
part-2/, https://www.baeldung.com/java-illegal-reflective-access, https://en.wikipedia.org/wiki/OSGi
137. 137/360
JEP-213: Milling Project Coin
From Java 7
– Allow @SafeVargs on private instance methods
– Allow effectively-final variables as resources in the try-
with-resources statement
– Allow diamond with anonymous classes in some cases
From Java 8
– Remove underscore as legal identifier names
In Java 9
– Support for private methods in interfaces
141. 141/360
Collection Factory Methods
No null values
No modification
– Run-time exception
public class Example1 {
public static void main(final String[] args) {
final List<String> list = List.of("Rick Deckard", "Roy Batty", "Harry Bryant", "Hannibal
Chew", "Gaff", "Holden", "Leon Kowalski", "Taffey Lewis", "Pris", "Rachael", "J.F.
Sebastian", "Dr. Eldon Tyrell", "Zhora", "Hodge", "Mary");
System.out.println(list);
list.add("Paul Atreides");
}
}
142. 142/360
Collection Factory Methods
No null values
No modification
– Run-time exception
public class Example1 {
public static void main(final String[] args) {
final List<String> list = List.of("Rick Deckard", "Roy Batty", "Harry Bryant", "Hannibal
Chew", "Gaff", "Holden", "Leon Kowalski", "Taffey Lewis", "Pris", "Rachael", "J.F.
Sebastian", "Dr. Eldon Tyrell", "Zhora", "Hodge", "Mary");
System.out.println(list);
list.add("Paul Atreides");
}
}
[Rick Deckard, Roy Batty, Harry Bryant, [...] Tyrell, Zhora, Hodge, Mary]
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
at [...]
at net.ptidej.newjava.collectionfactories.Example1.main(Example1.java:11)
143. 143/360
JavaDB Removal
JavaDB was a repackaging of Apache Derby
– Relational database
– Open-source
– Entirely in Java
– Embedded JDBC driver
144. 144/360
JEP-254: Compact Strings
Problem and Solution
More space-efficient
internal representation
– Not about using UTF-8
From a UTF-16 char
array to a byte array
with an encoding flag
– ISO-8859-1/Latin-1 (1 byte
per char) or UTF-16 (2 bytes)
– String-related classes and
HotSpot intrinsic operations
Consequences
Reduction in memory
footprint
Substantial reductions of
GC activity
Minor performance
regressions in some
corner cases
145. 145/360
JEP-263: HiDPI Graphics
Java programs sized and
rendered based on pixels
HiDPI displays can have 2
to 3 times higher pixel
densities
Windows Direct2D APIs
Linux GTK+ 3 libraries
https://stackoverflow.com/questions/52519777/java-swing-app-looks-tiny-on-high-dpi-screen-when-it-should-be-scaled-to-normal
146. 146/360
JEP-266: More on Concurrency
“[A]synchronous stream processing with
non-blocking back pressure”
– https://www.reactive-streams.org/
https://www.baeldung.com/java-9-reactive-streams
// Given
final SubmissionPublisher<String> publisher = new SubmissionPublisher<>();
final EndSubscriber<String> subscriber = new EndSubscriber<>();
final List<String> items = List.of("1", "x", "2", "x", "3", "x");
// When
publisher.subscribe(subscriber);
items.forEach(publisher::submit);
publisher.close();
// Then
Awaitility.await().atMost(1000, TimeUnit.MILLISECONDS)
.until(() -> subscriber.consumedElements.containsAll(items));
147. 147/360
JEP-268: XML Catalogs
OASIS XML Catalogs standard, v1.1
– Map XML external identifiers into (local) URIs
Java API
– javax.xml.catalog.*
<?xml version="1.0"?>
<!DOCTYPE catalog
PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN"
"http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="public">
<public publicId="-//W3C//DTD XHTML 1.0 Strict//EN"
uri="dtd/xhtml1/xhtml1-strict.dtd"/>
<public publicId="-//W3C//DTD XHTML 1.0 Transitional//EN"
uri="dtd/xhtml1/xhtml1-transitional.dtd"/>
<public publicId="-//W3C//DTD XHTML 1.1//EN"
uri="dtd/xhtml11/xhtml11-flat.dtd"/>
</catalog>
150. 150/360
JEP-282: jlink
Assemble, optimize some modules and their
dependencies into a custom run-time image
– JEP-220: Modular run-time images
javac -d out module-info.java
javac -d out --module-path out
netptidejnewjavajlinkHelloWorld.java
jlink --module-path "%JAVA_HOME%jmods";out
--add-modules testJLinkModule
--output CustomJRE
cd CustomJRE/bib/
java --module testJLinkModule/net.ptidej.newjava.jlink.HelloWorld
https://www.baeldung.com/jlink
151. 151/360
JEP-295: jaotc
Ahead-of-time compilation
– Compile Java classes to native code
before launching the virtual machine
https://stackoverflow.com/questions/45298045/how-do-i-run-a-class-compiled-with-jaotc
javac Test.java
jaotc Test.class
jaotc --output libjava.base.so --module java.base
java -XX:AOTLibrary=./Test.so Test
159. 159/360
JEP-312: Thread-local Handshakes
Callback on threads without performing a
global VM safepoint
Possible and cheap to stop individual
threads and not just all threads
-XX:ThreadLocalHandshakes=<true|false>
160. 160/360
JEP-316: Heap Allocation on
Alternative Memory Devices
Availability of cheap NVDIMM memory
– Non Volatile Dual In-line Memory Module
https://blog.workinghardinit.work/2019/07/18/a-quick-intro-to-nvdimm-n/
-XX:AllocateHeapAt=<path>
161. 161/360
JEP-317: Experimental Java-based
JIT Compiler
Efficient JIT compiler
for Java in Java
As of 18/09/30
https://www.graalvm.org/
https://www.javacodegeeks.com/2018/10/java-graalvm-database-stream-performance.html
-XX:+UnlockExperimentalVMOptions
-XX:+UseJVMCICompiler
163. 163/360
JEP-314: Additional Unicode
Language-Tag Extensions
BCP 47 language tags
– Codes to identify languages
• en: English
• en-US: English, in United States
• km-Khmr-KH: Khmer, in Khmer script, in Cambodia
• km-fonipa: Khmer, transcribed in IPA
Changes to many APIs
– java.text.DateFormat, java.util.Currency,
java.time.format.DateTimeFormatter, …
https://help.keyman.com/developer/current-version/reference/bcp-47
168. 168/360
JEP-319: Root Certificates
Default set of root Certification Authority
(CA) certificates
– Oracle Java SE Root CA becomes open source
– OpenJDK can use the same certificates
169. 169/360
JEP-322: Time-based Release
Versioning
New version scheme
final Version version = Runtime.version();
System.out.println(version);
System.out.print("Feature: ");
System.out.println(version.feature());
System.out.print("Interim: ");
System.out.println(version.interim());
System.out.print("Update: ");
System.out.println(version.update());
System.out.print("Patch: ");
System.out.println(version.patch());
System.out.print("Build: ");
System.out.println(version.build());
System.out.print("Optional: ");
System.out.println(version.optional());
System.out.print("Pre: ");
System.out.println(version.pre());
173. 173/360
JEP-181: Nest-based Access Control
Before Java 11
– Bridge method, e.g.,
access$000(Example1)
Since Java 11
– Direct access
– Access to nest mates’
private members
https://mkyong.com/java/java-11-nest-based-access-control/
public class Example1 {
private String name = "I'm Example1!";
public class A {
public void printName() {
System.out.println(name);
}
}
public class B {
public void printName() {
System.out.println(Example1.this.name);
}
public class B1 {
public void printName() {
System.out.println(Example1.this.name);
}
}
}
public static void main(final String[] args) {
final Example1 e1 = new Example1();
final Example1.B b = e1.new B();
final Example1.B.B1 b1 = b.new B1();
b1.printName();
}
}
174. 174/360
JEP-181: Nest-based Access Control
https://mkyong.com/java/java-11-nest-based-access-control/
public class Example2 {
private String name = "I'm Example2!";
public class A {
public void printName() {
System.out.println(name);
}
}
public class B {
public void printName() {
System.out.println(Example2.this.name);
}
public class B1 {
public void printName() {
System.out.println(Example2.this.name);
}
}
}
public static void main(final String[] args) {
System.out.println(A.class.getNestHost());
System.out.println(A.class.isNestmateOf(B.class));
for (final Class<?> clazz : Example2.B.class.getNestMembers()) {
System.out.println(clazz);
}
}
}
175. 175/360
JEP-181: Nest-based Access Control
https://mkyong.com/java/java-11-nest-based-access-control/
public class Example2 {
private String name = "I'm Example2!";
public class A {
public void printName() {
System.out.println(name);
}
}
public class B {
public void printName() {
System.out.println(Example2.this.name);
}
public class B1 {
public void printName() {
System.out.println(Example2.this.name);
}
}
}
public static void main(final String[] args) {
System.out.println(A.class.getNestHost());
System.out.println(A.class.isNestmateOf(B.class));
for (final Class<?> clazz : Example2.B.class.getNestMembers()) {
System.out.println(clazz);
}
}
}
class net.ptidej.newjava.nest.Example2
true
class net.ptidej.newjava.nest.Example2
class net.ptidej.newjava.nest.Example2$A
class net.ptidej.newjava.nest.Example2$B
class net.ptidej.newjava.nest.Example2$B$B1
176. 176/360
JEP-323: Local-variable Syntax for
Lambda Parameters
interface Comparator<T> {
int compare(final T a, final T b);
}
public class Example1 {
public static void main(final String[] args) {
final Comparator<String> comparator1 = new Comparator<>() {
@Override
public int compare(final String a, final String b) {
return a.compareTo(b);
}
};
System.out.println(comparator1.compare("Hello", "World"));
final Comparator<String> comparator2 = (a, b) -> a.compareTo(b);
System.out.println(comparator2.compare("Hello", "World"));
final Comparator<String> comparator3 = (String a, String b) -> a.compareTo(b);
System.out.println(comparator3.compare("Hello", "World"));
final Comparator<String> comparator4 = (final var a, final var b) -> a.compareTo(b);
System.out.println(comparator4.compare("Hello", "World"));
final Comparator<String> comparator5 = (@NonNull var a, @NonNull var b) -> a.compareTo(b);
System.out.println(comparator5.compare("Hello", "World"));
}
}
177. 177/360
JEP-323: Local-variable Syntax for
Lambda Parameters
interface Comparator<T> {
int compare(final T a, final T b);
}
public class Example1 {
public static void main(final String[] args) {
final Comparator<String> comparator1 = new Comparator<>() {
@Override
public int compare(final String a, final String b) {
return a.compareTo(b);
}
};
System.out.println(comparator1.compare("Hello", "World"));
final Comparator<String> comparator2 = (a, b) -> a.compareTo(b);
System.out.println(comparator2.compare("Hello", "World"));
final Comparator<String> comparator3 = (String a, String b) -> a.compareTo(b);
System.out.println(comparator3.compare("Hello", "World"));
final Comparator<String> comparator4 = (final var a, final var b) -> a.compareTo(b);
System.out.println(comparator4.compare("Hello", "World"));
final Comparator<String> comparator5 = (@NonNull var a, @NonNull var b) -> a.compareTo(b);
System.out.println(comparator5.compare("Hello", "World"));
}
}
Now posssible
179. 179/360
JEP-309: Dynamic .class Constants
Extend the class-file format with a new
constant-pool form
– CONSTANT_Dynamic
Avoid initialising “expansive” values
– Also, no need to use volatile
https://www.javacodegeeks.com/2018/08/hands-on-java-constantdynamic.html
180. 180/360
JEP-309: Dynamic .class Constants
Problem: How to share some “expensive” data
among different threads?
Solution: Singleton design pattern
public class SomeExpensiveData {
public SomeExpensiveData() {
// Some very expensive (time, space) data to create
System.out.println("tSomeExpensiveData instance created");
}
}
181. 181/360
JEP-309: Dynamic .class Constants
public class MyCallable implements Callable<SomeExpensiveData> {
private static MyCallable UniqueInstance;
public static MyCallable getInstance() {
if (MyCallable.UniqueInstance == null) {
synchronized (MyCallable.class) {
if (MyCallable.UniqueInstance == null) {
MyCallable.UniqueInstance = new MyCallable();
}
}
}
return MyCallable.UniqueInstance;
}
private volatile SomeExpensiveData someExpensiveData;
private MyCallable() {
this.someExpensiveData = new SomeExpensiveData();
}
@Override
public SomeExpensiveData call() throws Exception {
return this.someExpensiveData;
}
}
182. 182/360
JEP-309: Dynamic .class Constants
public class MyCallable implements Callable<SomeExpensiveData> {
private static MyCallable UniqueInstance;
public static MyCallable getInstance() {
if (MyCallable.UniqueInstance == null) {
synchronized (MyCallable.class) {
if (MyCallable.UniqueInstance == null) {
MyCallable.UniqueInstance = new MyCallable();
}
}
}
return MyCallable.UniqueInstance;
}
private volatile SomeExpensiveData someExpensiveData;
private MyCallable() {
this.someExpensiveData = new SomeExpensiveData();
}
@Override
public SomeExpensiveData call() throws Exception {
return this.someExpensiveData;
}
}
Not a true constant
No caching, etc.
183. 183/360
JEP-309: Dynamic .class Constants
public class MyCallable implements Callable<SomeExpensiveData> {
private static MyCallable UniqueInstance;
public static MyCallable getInstance() {
if (MyCallable.UniqueInstance == null) {
synchronized (MyCallable.class) {
if (MyCallable.UniqueInstance == null) {
MyCallable.UniqueInstance = new MyCallable();
}
}
}
return MyCallable.UniqueInstance;
}
private volatile SomeExpensiveData someExpensiveData;
private MyCallable() {
this.someExpensiveData = new SomeExpensiveData();
}
@Override
public SomeExpensiveData call() throws Exception {
return this.someExpensiveData;
}
}
Not a true constant
No caching, etc.
Eager initialisation
184. 184/360
JEP-309: Dynamic .class Constants
Dynamic constants
– Created once at run-time
– Can be shared among threads
– Can be cached, optimised, etc.
Problem: How to create dynamically a constant
Solution: CONSTANT_Dynamic
185. 185/360
JEP-309: Dynamic .class Constants
Dynamic constants, javac vs. java
– Cannot be created from source code
• As of 24/03/24
– Can be created in the byte code
Byte code generation, manipulation library
– Create, modify Java classes at run-time
186. 186/360
JEP-309: Dynamic .class Constants
final Unloaded<Callable> unloaded = new ByteBuddy().subclass(Callable.class)
.method(ElementMatchers.named("call")).intercept(FixedValue.value(
JavaConstant.Dynamic.ofInvocation(SomeExpensiveData.class.getConstructor()))).make();
final Constructor<? extends Callable> loaded =
unloaded.load(Example2.class.getClassLoader()).getLoaded().getConstructor();
final Callable<SomeExpensiveData> first = loaded.newInstance();
final Callable<SomeExpensiveData> second = loaded.newInstance();
System.out.println("tCallable instances created");
assertThat(first.call()).isEqualTo(second.call());
187. 187/360
JEP-309: Dynamic .class Constants
final Unloaded<Callable> unloaded = new ByteBuddy().subclass(Callable.class)
.method(ElementMatchers.named("call")).intercept(FixedValue.value(
JavaConstant.Dynamic.ofInvocation(SomeExpensiveData.class.getConstructor()))).make();
final Constructor<? extends Callable> loaded =
unloaded.load(Example2.class.getClassLoader()).getLoaded().getConstructor();
final Callable<SomeExpensiveData> first = loaded.newInstance();
final Callable<SomeExpensiveData> second = loaded.newInstance();
System.out.println("tCallable instances created");
assertThat(first.call()).isEqualTo(second.call());
test_CONSTANT_Dynamic()
Callable instances created
SomeExpensiveData instance created
188. 188/360
JEP-309: Dynamic .class Constants
final Unloaded<Callable> unloaded = new ByteBuddy().subclass(Callable.class)
.method(ElementMatchers.named("call")).intercept(FixedValue.value(
JavaConstant.Dynamic.ofInvocation(SomeExpensiveData.class.getConstructor()))).make();
final Constructor<? extends Callable> loaded =
unloaded.load(Example2.class.getClassLoader()).getLoaded().getConstructor();
final Callable<SomeExpensiveData> first = loaded.newInstance();
final Callable<SomeExpensiveData> second = loaded.newInstance();
System.out.println("tCallable instances created");
assertThat(first.call()).isEqualTo(second.call());
test_CONSTANT_Dynamic()
Callable instances created
SomeExpensiveData instance created
Lazy initialisation: two
instances created, but not
SomExpensiveData
189. 189/360
JEP-309: Dynamic .class Constants
final Unloaded<Callable> unloaded = new ByteBuddy().subclass(Callable.class)
.method(ElementMatchers.named("call")).intercept(FixedValue.value(
JavaConstant.Dynamic.ofInvocation(SomeExpensiveData.class.getConstructor()))).make();
final Constructor<? extends Callable> loaded =
unloaded.load(Example2.class.getClassLoader()).getLoaded().getConstructor();
final Callable<SomeExpensiveData> first = loaded.newInstance();
final Callable<SomeExpensiveData> second = loaded.newInstance();
System.out.println("tCallable instances created");
assertThat(first.call()).isEqualTo(second.call());
test_CONSTANT_Dynamic()
Callable instances created
SomeExpensiveData instance created
Lazy initialisation: two
instances created, but not
SomExpensiveData
SomExpensiveData created
only once, with first call()
190. 190/360
JEP-309: Dynamic .class Constants
final Unloaded<Callable> unloaded = new ByteBuddy().subclass(Callable.class)
.method(ElementMatchers.named("call")).intercept(FixedValue.value(
JavaConstant.Dynamic.ofInvocation(SomeExpensiveData.class.getConstructor()))).make();
final Constructor<? extends Callable> loaded =
unloaded.load(Example2.class.getClassLoader()).getLoaded().getConstructor();
final Callable<SomeExpensiveData> first = loaded.newInstance();
final Callable<SomeExpensiveData> second = loaded.newInstance();
System.out.println("tCallable instances created");
assertThat(first.call()).isEqualTo(second.call());
// (version 17 : 61.0, super bit)
public class net.bytebuddy.[...].Callable$ByteBuddy$7xbn1EIQ implements java.util.concurrent.Callable
public java.lang.Object call() throws java.lang.Exception;
0 ldc <Dynamic> 0 _ net.ptidej.newjava.constantdynamic.SomeExpensiveData [28]
2 areturn
public Callable$ByteBuddy$7xbn1EIQ();
0 aload_0 [this]
1 invokespecial java.lang.Object() [29]
4 return
Bootstrap methods:
0 : # 24 invokestatic java/lang/invoke/ConstantBootstraps.invoke:([...])Ljava/lang/Object;
Method arguments:
#17 net/ptidej/newjava/constantdynamic/SomeExpensiveData.<init>:()V
191. 191/360
JEP-309: Dynamic .class Constants
final Unloaded<Callable> unloaded = new ByteBuddy().subclass(Callable.class)
.method(ElementMatchers.named("call")).intercept(FixedValue.value(
JavaConstant.Dynamic.ofInvocation(SomeExpensiveData.class.getConstructor()))).make();
final Constructor<? extends Callable> loaded =
unloaded.load(Example2.class.getClassLoader()).getLoaded().getConstructor();
final Callable<SomeExpensiveData> first = loaded.newInstance();
final Callable<SomeExpensiveData> second = loaded.newInstance();
System.out.println("tCallable instances created");
assertThat(first.call()).isEqualTo(second.call());
// (version 17 : 61.0, super bit)
public class net.bytebuddy.[...].Callable$ByteBuddy$7xbn1EIQ implements java.util.concurrent.Callable
public java.lang.Object call() throws java.lang.Exception;
0 ldc <Dynamic> 0 _ net.ptidej.newjava.constantdynamic.SomeExpensiveData [28]
2 areturn
public Callable$ByteBuddy$7xbn1EIQ();
0 aload_0 [this]
1 invokespecial java.lang.Object() [29]
4 return
Bootstrap methods:
0 : # 24 invokestatic java/lang/invoke/ConstantBootstraps.invoke:([...])Ljava/lang/Object;
Method arguments:
#17 net/ptidej/newjava/constantdynamic/SomeExpensiveData.<init>:()V
CONSTANT_Dynamic
with bootstrap method
192. 192/360
JEP-331: Low-overhead Heap
Profiling
Since Java 6
– No more JVM Profiler
Interface (JVMPI)
– No more JVM Debug
Interface (JVMDI)
– Replaced by JVM Tool
Interface (JVMTI)
Sampling of Java heap
allocations
– All allocations
– Low-overhead
– Well-defined API
– Live, dead objects
https://docs.oracle.com/en/java/javase/11/docs/specs/jvmti.html
194. 194/360
JEP-333: Scalable Low-latency GC
Z Garbage Collector
– GC pause no more than 10ms
– Handle megabyte to terabyte heaps
– No more than 15% throughput reduction wrt. G1
– Foundation for future features and optimisations
– (Only on 64bit operating systems)
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
196. 196/360
JEP-320: Java EE and CORBA
Modules Removal
Since Java 1.2
– OMG CORBA API
– ORB implementation
– CosNaming implementation
– idlj compiler
– Support for IDL and IIOP in rmic compiler
– No significant interest in CORBA anymore
Since Java 6
– Full Web Services stack
– Now available from third parties
Deprecated in Java 9
197. 197/360
JEP-321: HTTP Client
Problems with HttpURLConnection API
– Designed for (now dead) protocols (gopher…)
– Designed before HTTP/1.1
– Too abstract
– Hard to use
– Badly documented
– Blocking mode only
– Very hard maintenance
198. 198/360
JEP-321: HTTP Client
Three core classes
– HttpClient as a container for configuration
information common to multiple requests
– HttpRequest for requests sent by HttpClient
– HttpResponse for the result of an HttpRequest
https://www.baeldung.com/java-9-http-client
201. 201/360
JEP-327: Unicode 10
Major version of the Unicode Standard
Support
– Character and String in java.lang
– NumericShaper in java.awt.font
– Bidi, BreakIterator, Normalizer in java.text
202. 202/360
JEP-335: Nashorn Deprecation
Since Java 8
– JEP-174
ECMAScript changes rapidly
– Language
– APIs
Maintenance challenges
– Deprecate Nashorn, its APIs, and jjs
204. 204/360
JEP-328: Flight Recorder
Monitoring tool
– Collects information about the events in a JVM
– An event
• Name
• Timestamp
• Other data
– Thread data, state of the heap, etc.
https://www.baeldung.com/java-flight-recorder-monitoring
-XX:+UnlockCommercialFeatures
-XX:+FlightRecorder
-XX:StartFlightRecording=duration=200s,filename=flight.jfr
207. 207/360
JEP-336: Pack200 Tools and API
Deprecation
Since Java 5
– Compression scheme for JAR files
– To accommodate 56k modems
Since Java 9 (and JEP-220)
– Modules
– Compression
– No more applets
– Maintenance challenges
– Modularisation challenges
212. 212/360
JEP-344: Abortable Mixed
Collections
Ability for G1 to abort its collection pauses
G1 predicts the number of regions to collect
and proceeds only with abortable ones
Lower pause latency and higher probability
to achieve pause-time target
https://blogs.oracle.com/javamagazine/post/understanding-the-jdks-new-superfast-garbage-collectors
-XX:G1MixedGCCountTarget=<number of mixed garbage collections>
213. 213/360
JEP-346: Unused Committed
Memory Prompt Return
G1 automatically returns heap memory to
the operating system when idle
-XX:G1PeriodicGCInterval=<true|false>
-XX:G1PeriodicGCInvokesConcurrent=<true|false>
-XX:G1PeriodicGCSystemLoadThreshold=<average 1-minute system load>
215. 215/360
JEP-334: JVM Constants API
API to describes some class-file and run-
time elements (e.g., constants)
https://iampravo.medium.com/java-12-features-and-highlights-81938474cd31
public class Example1 {
public static void main(final String[] args) {
final ClassDesc example1ClassDesc = ClassDesc.of("[...].constantsapi", "Example1");
final MethodTypeDesc mainMethodTypeDesc = MethodTypeDesc.of(example1ClassDesc);
final MethodHandleDesc mainMethodHandleDesc = MethodHandleDesc.ofMethod(
DirectMethodHandleDesc.Kind.STATIC, example1ClassDesc, "main", mainMethodTypeDesc);
System.out.println("Class descriptor: " + example1ClassDesc);
System.out.println("Method type descriptor: " + mainMethodTypeDesc);
System.out.println("Method handle descriptor: " + mainMethodHandleDesc);
}
}
216. 216/360
JEP-334: JVM Constants API
API to describes some class-file and run-
time elements (e.g., constants)
https://iampravo.medium.com/java-12-features-and-highlights-81938474cd31
public class Example1 {
public static void main(final String[] args) {
final ClassDesc example1ClassDesc = ClassDesc.of("[...].constantsapi", "Example1");
final MethodTypeDesc mainMethodTypeDesc = MethodTypeDesc.of(example1ClassDesc);
final MethodHandleDesc mainMethodHandleDesc = MethodHandleDesc.ofMethod(
DirectMethodHandleDesc.Kind.STATIC, example1ClassDesc, "main", mainMethodTypeDesc);
System.out.println("Class descriptor: " + example1ClassDesc);
System.out.println("Method type descriptor: " + mainMethodTypeDesc);
System.out.println("Method handle descriptor: " + mainMethodHandleDesc);
}
}
Class descriptor: ClassDesc[Example1]
Method type descriptor: MethodTypeDesc[()Example1]
Method handle descriptor: MethodHandleDesc[STATIC/Example1::main()Example1]
218. 218/360
JEP-230: Microbenchmark Suite
Java Microbenchmark Harness (JMH)
– An annotation-based DSL
• @State, @Fork, @Warmup, @Measurement, @Benchmark…
Microbenchmarks suite integrated into
OpenJDK source code
https://cl4es.github.io/2018/11/16/JEP-230-Microbenchmarks-Suite.html
make build-microbenchmark
219. 219/360
JEP-230: Microbenchmark Suite
Java Microbenchmark Harness (JMH)
– An annotation-based DSL
• @State, @Fork, @Warmup, @Measurement, @Benchmark…
Microbenchmarks suite integrated into
OpenJDK source code
https://cl4es.github.io/2018/11/16/JEP-230-Microbenchmarks-Suite.html
make build-microbenchmark
build/$PROFILE/images/test/micro/benchmarks.jar
220. 220/360
JEP-230: Microbenchmark Suite
Run one java.util.UUIDBench benchmark
– https://github.com/openjdk/jdk/blob/master/test/mi
cro/org/openjdk/bench/java/util/UUIDBench.java
https://cl4es.github.io/2021/01/04/Investigating-MD5-Overheads.html
make test TEST=micro:UUIDBench.fromType3Bytes
221. 221/360
JEP-230: Microbenchmark Suite
Run one java.util.UUIDBench benchmark
– https://github.com/openjdk/jdk/blob/master/test/mi
cro/org/openjdk/bench/java/util/UUIDBench.java
https://cl4es.github.io/2021/01/04/Investigating-MD5-Overheads.html
make test TEST=micro:UUIDBench.fromType3Bytes
Benchmark Score Error Units
fromType3Bytes 1.460 ± 0.089 ops/us
222. 222/360
JEP-230: Microbenchmark Suite
Benchmarking the
JVM is difficult
– Just-in-time compiler
– Dead code elimination
– Loop unrolling
– Method inlining
– …
– Warmup iterations
– Iteration durations
– …
https://www.oracle.com/technical-resources/articles/java/architect-benchmarking.html
235. 235/360
-XX:+ShowCodeDetailsInExceptionMessages
JEP-358: Helpful
NullPointerExceptions
Describe precisely which variable was null
class Employee {
String getName() {
// return "Bob";
return null;
}
}
public class Example1 {
public static void main(final String[] args) {
final Employee e = new Employee();
e.getName().toString();
}
}
Exception in thread "main" java.lang.NullPointerException
at net.ptidej.newjava.helpfulnullpointerexceptions.Example1.main(Example1.java:13)
236. 236/360
-XX:+ShowCodeDetailsInExceptionMessages
JEP-358: Helpful
NullPointerExceptions
Describe precisely which variable was null
class Employee {
String getName() {
// return "Bob";
return null;
}
}
public class Example1 {
public static void main(final String[] args) {
final Employee e = new Employee();
e.getName().toString();
}
}
Exception in thread "main" java.lang.NullPointerException
at net.ptidej.newjava.helpfulnullpointerexceptions.Example1.main(Example1.java:13)
Exception in thread "main" java.lang.NullPointerException: Cannot invoke
"String.toString()" because the return value of "[...].Employee.getName()" is null
at net.ptidej.newjava.helpfulnullpointerexceptions.Example1.main(Example1.java:13)
237. 237/360
JEP-361: switch Expressions
https://medium.com/@imagarg/switch-expression-jep-361-3b5649ec36c9
private static int getDayLength(final Day day) {
int numberOfCharacters = 0;
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numberOfCharacters = 6;
break;
case TUESDAY:
numberOfCharacters = 7;
break;
case THURSDAY:
case SATURDAY:
numberOfCharacters = 8;
break;
case WEDNESDAY:
numberOfCharacters = 9;
break;
default:
throw new IllegalArgumentException();
}
return numberOfCharacters;
}
private static int getDayLength(final Day day) {
int result = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
default ->
throw new IllegalArgumentException();
};
return result;
}
enum Day {
MONDAY, TUESDAY,
WEDNESDAY,
THURSDAY, FRIDAY,
SATURDAY, SUNDAY;
}