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.24
2025/03/18
2/466
Any questions/comments are welcome at
yann-gael.gueheneuc@concordia.ca
Source code available at
https://github.com/ptidejteam/tutorials-NewJava
3/466
Patrick Naughton
Scott McNealy
Mike Sheridan James Gosling
1991
4/466
5/466
Naming
 Java
– 1995/05/23
– Language
 JDK (Java Development Kit)
– Compiler (Java Language Specification)
– VM (Java Virtual Machine Specification)
– APIs/Libraries (Java Class Libraries)
6/466
Process
 JCP: Java Community Process
– Established in 1998
– JSR-387 describes JCP v2.11
7/466
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
8/466
About the JDK
https://medium.com/@zaam.oussama/java-development-kit-jdk-exploring-its-components-and-functionality-8f6d6c2a046c
9/466
About the JDK
 Compiler
– javac: compiler
 Development
– javadoc: documentation
– jar: packaging
– jdb: debugger
 Management
– jconsole: GUI
– javaw: VM
 Libraries
– java.lang.…: mandatory
classes
– java.awt.…: graphical
framework
– javax.…: extensions
https://medium.com/@zaam.oussama/java-development-kit-jdk-exploring-its-components-and-functionality-8f6d6c2a046c
10/466
About the JDK
https://medium.com/@zaam.oussama/java-development-kit-jdk-exploring-its-components-and-functionality-8f6d6c2a046c
11/466
About the JDK
https://medium.com/@zaam.oussama/java-development-kit-jdk-exploring-its-components-and-functionality-8f6d6c2a046c
12/466
About the JDK
 Loading: JVM loads bytecode in .class files
 Verification: JVM verifies the bytecode for
Java’s safety and security rules
 Execution: JVM interprets or compiles
bytecode into native machine instructions
 Optimization: JIT compiler optimises
bytecode for faster execution
https://medium.com/@zaam.oussama/java-development-kit-jdk-exploring-its-components-and-functionality-8f6d6c2a046c
13/466
About the JDK
 Modularisation
– Since Java 9 (2017)
 Development
– jlink: assembles and
optimises a set of modules
and their dependencies into
a custom runtime image
– jpackage: generates
installable packages for
(non-)modular programs
– jmod: packages modules
with native libraries or other
configuration files (for jlink)
 Runtime
– A JDK image is a runtime
image with development
tools
– A runtime image is a set of
folders/files
– URI scheme jrt:/ for
naming stored modules,
classes, and resources
– No regression
• Startup
• Static footprint
• Dynamic footprint
14/466
About the JDK
https://bugs.openjdk.org/secure/attachment/72525/jdk.png
15/466
Disclaimer
16/466
Too
Many
Features
Disclaimer
No
Preview
No
Incubator
Or just a few…
17/466
Organisation
 Per release
– With some cross-references
 Three categories
– Language
– JVM
– APIs
Misc
+
18/466
In Summary
(With Few Examples)
 Language
– Reduce risk of bugs
• try with resources
– Simplify coding
• switch with Strings, expressions, pattern matching
– Improve typing
• Diamond operator, annotations, inferences
– Make the language more functional
• λ-expressions (+ rewrite of many APIs)
– Control finely accessibility/visibility
• Modules, records, sealed classes, hidden classes
19/466
In Summary
(With Few Examples)
 JVM
– APIs
• Tools
• GCs
– Release
• Statically-linked libraries
– Performance
• JIT
– Graal VM
• GCs
– Implementations
– NUMA
20/466
In Summary
(With Few Examples)
 APIs
– Reduce risk of bugs
• Concurrency
• Date and Time
– Simplify coding
• New file I/O
• HTTP client and server
• Foreign Function and Memory API
21/466
In Summary
(With Few Examples)
 Misc.
– Coding
• jshell
• Java files launching
• Instance main method
– Release
• jlink and jpackage
– Performance
• jaotc
22/466
Java 5
Java 6
2004/09/30
2006/12/11
23/466
LANGUAGE (ONLY)
24/466
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();
}
}
25/466
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);
}
26/466
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()
27/466
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();
}
}
28/466
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
29/466
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
30/466
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 // ...
}
31/466
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
32/466
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;
33/466
Java 7
2011/07/07
2011/07/07
34/466
LANGUAGE
35/466
Strings in switch
https://www.baeldung.com/java-switch
public String exampleOfSwitch(String animal) {
String result;
switch (animal) {
case "DOG" :
result = "domestic animal";
break;
case "CAT" :
result = "domestic animal";
break;
case "TIGER" :
result = "wild animal";
break;
default :
result = "unknown animal";
break;
}
return result;
}
36/466
try With Resources
 New interfaces
– java.lang.Closeable
– java.lang.AutoCloseable
https://www.baeldung.com/java-try-with-resources
try (final Scanner scanner = new Scanner(new File("test.txt"))) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
}
catch (final FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
37/466
Diamond Operator <>
https://www.baeldung.com/java-diamond-operator
List<String> cars = new ArrayList<String>();
List<String> cars = new ArrayList<>();
vs.
38/466
Vargs in Method Declaration
https://www.baeldung.com/java-varargs
https://www.baeldung.com/java-varargs
public String format() {
// ...
}
public String format(String value) {
//...
}
public String format(String val1, String val2) {
// ...
}
public String formatWithVarArgs(String... values) {
System.out.println(values[0]);
System.out.println(values[1]);
System.out.println(values[3]);
// ...
}
vs.
39/466
Binary Integer Literals
https://www.geeksforgeeks.org/java-program-to-illustrate-use-of-binary-literals/
// Byte type Binary Literal
byte a1 = 0b011;
// Short type Binary Literal
short b1 = 0b101;
// Int type Binary literal
int c1 = 0b011;
// Long type Binary literal
long d1 = 0b0000011111100011;
40/466
Underscores in Numeric Literals
int i = 12_34_56;
System.out.println(i);
https://www.geeksforgeeks.org/using-underscore-numeric-literals-java/
41/466
Multiple Exception Types
 Multiple exception types
 Multiple exceptions rethrown
with improved type checking
42/466
Multiple Exception Types
public static void main(final String[] args) {
try {
Example1.rethrow("abc");
}
catch (final FirstException | SecondException e) {
// Below assignment would throw a compile-time exception, e is implicitly final
// e = new Exception();
System.out.println(e.getMessage());
}
}
private static void rethrow(final String s) throws FirstException, SecondException {
try {
if (s.equals("First")) throw new FirstException("First");
else throw new SecondException("Second");
}
catch (final Exception e) {
// Below assignment would disable improved rethrow exception type checking
// e = new ThirdException();
throw e;
}
}
private static class FirstException extends Exception {
public FirstException(String msg) {
super(msg);
}
}
// ...
43/466
JVM
44/466
JSR-292: invokedynamic
 invokestatic, for class methods
 invokevirtual, for instance methods
 invokeinterface, for interface methods
 invokespecial, for instance initialisation,
superclass, and private methods
45/466
JSR-292: invokedynamic
Gilad Bracha, 2005
46/466
JSR-292: invokedynamic
 invokedynamic indicates that a dynamic
language run-time specific call occurs
 The call occurs through MethodHandle(s)
https://www.baeldung.com/java-method-handles
MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
MethodType mt = MethodType.methodType(String.class, char.class, char.class);
MethodHandle replaceMH = publicLookup.findVirtual(String.class, "replace", mt);
String output = (String) replaceMH.invoke("jovo", 'o', 'a');
47/466
APIS
48/466
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
49/466
JSR-166: Concurrency Utilities
https://www.uml-diagrams.org/java-7-concurrent-uml-class-diagram-example.html
50/466
JSR-166: Concurrency Utilities
https://www.uml-diagrams.org/java-7-concurrent-uml-class-diagram-example.html
51/466
JSR-166: Concurrency Utilities
https://www.uml-diagrams.org/java-7-concurrent-uml-class-diagram-example.html
52/466
JSR-166: Concurrency Utilities
https://gee.cs.oswego.edu/dl/concurrency-interest/jsr166-slides.pdf
final Runnable runnable1 = new RunnableExample("executor.execute(...)");
final ExecutorService executor = Executors.newFixedThreadPool(10);
executor.execute(runnable1);
final Runnable runnable2 = new RunnableExample("new Thread(...)");
new Thread(runnable2).start();
vs.
53/466
JSR-166: Concurrency Utilities
class ImageRenderer {
Image render(final byte[] raw) {
return // ...
}
}
public class Example2 {
public void display(final byte[] raw) throws InterruptedException, ExecutionException {
final ExecutorService executor = Executors.newFixedThreadPool(10);
final ImageRenderer renderer = new ImageRenderer();
final Future<Image> image = executor.submit(new Callable<Image>() {
public Image call() {
return renderer.render(raw);
}
});
drawBorders(); // do other things ...
drawCaption(); // ... while executing
drawImage(image.get()); // use Future
}
// ...
https://gee.cs.oswego.edu/dl/concurrency-interest/jsr166-slides.pdf
54/466
JSR-166: Concurrency Utilities
public void run() {
synchronized (this.resource) {
this.resource.doSomething();
}
this.resource.doLogging();
}
public void run() {
try {
if (this. lock.tryLock(10, TimeUnit.SECONDS)) {
this.resource.doSomething();
}
}
catch (final InterruptedException exception) {
exception.printStackTrace();
}
finally {
this.lock.unlock();
}
this.resource.doLogging();
}
vs.
https://www.digitalocean.com/com
munity/tutorials/java-lock-example-
reentrantlock
55/466
JSR-166: Concurrency Utilities
https://www.geeksforgeeks.org/semaphore-in-java/
private final Semaphore semaphore;
private void connect(final String user)
throws InterruptedException {
System.out.println(getCurrentDateTime()
+ " : " + user + " waiting sem");
this.semaphore.acquire();
System.out.println(getCurrentDateTime()
+ " : " + user + " acquired sem");
Thread.sleep(1000); // Some work...
this.semaphore.release();
System.out.println(getCurrentDateTime()
+ " : " + user + " released sem");
}
https://mkyong.com/java/java-semaphore-examples/
56/466
JSR-166: Concurrency Utilities
https://www.geeksforgeeks.org/atomic-variables-in-java-with-examples/
class Counter extends Thread {
private final AtomicInteger count;
public Counter() {
this.count = new AtomicInteger();
}
public void run() {
final int max = 10_000_000;
for (int i = 0; i < max; i++) {
count.addAndGet(1);
}
}
public int getCount() {
return this.count.get();
}
}
57/466
JSR-203: New File I/O Library
 Extensive File I/O API
 Socket channel API
 Asynchronous I/O API
58/466
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);
}
}
59/466
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;
}
}
60/466
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
61/466
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();
}
62/466
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
63/466
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”
64/466
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)
65/466
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();
// ...
66/466
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
67/466
Java 8
2014/03/18
68/466
LANGUAGE
69/466
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());
}
70/466
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
71/466
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());
}
72/466
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());
}
73/466
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());
74/466
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
75/466
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!"));
}
76/466
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!"));
}
77/466
JSR-335, JEP-126: λ Expressions
 Solution
– Simple syntactic sugar
– Set of functional interfaces
– Libraries using these interfaces
78/466
JSR-335, JEP-126: λ Expressions
 Solution
– Simple syntactic sugar
– Set of functional interfaces
– Libraries using these interfaces
79/466
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!"));
}
80/466
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!"));
}
81/466
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
82/466
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
83/466
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
84/466
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> namesStartingWithR = friends.stream().
filter(name -> name.startsWith("R")).collect(Collectors.toList());
System.out.println(namesStartingWithR);
85/466
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.
86/466
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.
87/466
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.
88/466
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.
89/466
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);
}
}
90/466
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);
}
}
91/466
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
92/466
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
93/466
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);
}
}
}
94/466
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'
95/466
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/
96/466
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)");
}
}
}
97/466
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/
98/466
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/
99/466
JEP-120: Repeating Annotations
https://rolyhewage.medium.com/type-annotations-repeating-annotations-in-java-722073df9f99
@Retention(RetentionPolicy.RUNTIME)
@interface ScheduleNonRepeatable1 {
String dayOfMonth() default "First";
String dayOfWeek() default "Mon";
int hour() default 12;
}
@ScheduleNonRepeatable1(dayOfWeek = "Fri", hour = 23)
public class Example1 {
public static void main(final String[] args) {
final Example1 example1 = new Example1();
final Annotation annotation = example1.getClass().
getAnnotation(ScheduleNonRepeatable1.class);
System.out.println(annotation);
}
}
100/466
JEP-120: Repeating Annotations
https://rolyhewage.medium.com/type-annotations-repeating-annotations-in-java-722073df9f99
@Retention(RetentionPolicy.RUNTIME)
@interface ScheduleNonRepeatable1 {
String dayOfMonth() default "First";
String dayOfWeek() default "Mon";
int hour() default 12;
}
@ScheduleNonRepeatable1(dayOfWeek = "Fri", hour = 23)
public class Example1 {
public static void main(final String[] args) {
final Example1 example1 = new Example1();
final Annotation annotation = example1.getClass().
getAnnotation(ScheduleNonRepeatable1.class);
System.out.println(annotation);
}
}
@ScheduleNonRepeatable1(hour=23, dayOfMonth="First", dayOfWeek="Fri")
101/466
JEP-120: Repeating Annotations
https://rolyhewage.medium.com/type-annotations-repeating-annotations-in-java-722073df9f99
@Retention(RetentionPolicy.RUNTIME)
@interface ScheduleNonRepeatable2 {
String dayOfMonth() default "First";
String dayOfWeek() default "Mon";
int hour() default 12;
}
@ScheduleNonRepeatable2(dayOfMonth = "last")
@ScheduleNonRepeatable2(dayOfWeek = "Fri", hour = 23)
public class Example2 {
public static void main(final String[] args) {
final Example2 example2 = new Example2();
final Annotation annotation = example2.getClass().
getAnnotation(ScheduleNonRepeatable2.class);
System.out.println(annotation);
}
}
102/466
JEP-120: Repeating Annotations
https://rolyhewage.medium.com/type-annotations-repeating-annotations-in-java-722073df9f99
@Retention(RetentionPolicy.RUNTIME)
@interface ScheduleNonRepeatable2 {
String dayOfMonth() default "First";
String dayOfWeek() default "Mon";
int hour() default 12;
}
@ScheduleNonRepeatable2(dayOfMonth = "last")
@ScheduleNonRepeatable2(dayOfWeek = "Fri", hour = 23)
public class Example2 {
public static void main(final String[] args) {
final Example2 example2 = new Example2();
final Annotation annotation = example2.getClass().
getAnnotation(ScheduleNonRepeatable2.class);
System.out.println(annotation);
}
}
Duplicate annotation of
non-repeatable type
@ScheduleNonRepeatable2
103/466
JEP-120: Repeating Annotations
https://rolyhewage.medium.com/type-annotations-repeating-annotations-in-java-722073df9f99
@Retention(RetentionPolicy.RUNTIME)
@interface Schedules {
ScheduleRepeatable[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Schedules.class)
@interface ScheduleRepeatable {
String dayOfMonth() default "First";
String dayOfWeek() default "Mon";
int hour() default 12;
}
@ScheduleRepeatable(dayOfMonth = "last")
@ScheduleRepeatable(dayOfWeek = "Fri", hour = 23)
public class Example3 {
public static void main(final String[] args) {
final Example3 example3 = new Example3();
final Annotation annotation = example3.getClass().
getAnnotation(Schedules.class);
System.out.println(annotation);
}
}
104/466
JEP-120: Repeating Annotations
https://rolyhewage.medium.com/type-annotations-repeating-annotations-in-java-722073df9f99
@Retention(RetentionPolicy.RUNTIME)
@interface Schedules {
ScheduleRepeatable[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Schedules.class)
@interface ScheduleRepeatable {
String dayOfMonth() default "First";
String dayOfWeek() default "Mon";
int hour() default 12;
}
@ScheduleRepeatable(dayOfMonth = "last")
@ScheduleRepeatable(dayOfWeek = "Fri", hour = 23)
public class Example3 {
public static void main(final String[] args) {
final Example3 example3 = new Example3();
final Annotation annotation = example3.getClass().
getAnnotation(Schedules.class);
System.out.println(annotation);
}
}
@Schedules({@ScheduleRepeatable(hour=12, dayOfMonth="last", dayOfWeek="Mon"),
@ScheduleRepeatable(hour=23, dayOfMonth="First", dayOfWeek="Fri")})
105/466
JVM
106/466
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
107/466
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
108/466
APIS
109/466
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
110/466
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);
111/466
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.*
112/466
MISC
113/466
JEP-153: JavaFX Applications
 Three “types” of programs
– Class files
– JAR files
– JavaFX
 Enhance the java command-line to launch
JavaFX programs
114/466
Java 9
2017/09/21
115/466
LANGUAGE
116/466
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());
}
117/466
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
118/466
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/
119/466
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
120/466
JSR-376: Modularization
 Classpath / JARs Hell
 Version conflicts
 Large Monolithic JDK
 Security Problems
https://www.geeksforgeeks.org/jpms-java-platform-module-system/
121/466
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/
122/466
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/
123/466
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/
124/466
JSR-376: Modularization
125/466
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
126/466
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;
}
127/466
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;
}
128/466
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;
}
129/466
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;
}
130/466
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;
}
131/466
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
132/466
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
133/466
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!)
134/466
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
135/466
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
...
136/466
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
137/466
JSR-376: Modularization
 Client
 Provider
module ModularizationWithModulesClient1 {
requires ModularizationWithModulesLibrary1;
}
module ModularizationWithModulesLibrary1 {
exports net.ptidej.modularisation.kernel;
exports net.ptidej.modularisation.kernel.impl;
}
138/466
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
139/466
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
140/466
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
141/466
JSR-376: Modularization
 Client
 Provider
module ModularizationWithModulesClient2 {
requires ModularizationWithModulesLibrary2;
uses net.ptidej.modularisation.kernel.Interface;
}
module ModularizationWithModulesLibrary2 {
exports net.ptidej.modularisation.kernel;
provides
net.ptidej.modularisation.kernel.Interface with
net.ptidej.modularisation.kernel.impl.Implementation;
}
142/466
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();
143/466
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();
144/466
JSR-376: Modularization
 Accessibility
– Observability
– Readability
• requires vs. requires transitive
– Visibility
• public vs. “default”
Problem: How to decide what packages and
types are accessible?
Solution: Readability vs. Visibility
145/466
JSR-376: Modularization
 Accessibility (bis)
– Compile-time, run-time: --add-exports
• Access to public types not exported via the module
descriptor, for compilation and execution
– Run-time only: --add-opens
• Access to all types not exported via the module
descriptor through reflection (cf. setAccessible())
146/466
JSR-376: Modularization
https://www.baeldung.com/java-illegal-reflective-access
 Backward compatibility
 Automatic module name
– Classpath vs. Module path
– JAR found on the module path
147/466
JSR-376: Modularization
https://medium.com/@dvsingh9/java-modules-a-complete-guide-part-2-340e5b8d26
148/466
JSR-376: Modularization
https://docs.oracle.com/javase%2F9%2Fdocs%2Fapi%2F%2F/overview-summary.html
149/466
JSR-376: Modularization
https://docs.oracle.com/javase%2F9%2Fdocs%2Fapi%2F%2F/java/lang/Module.html
150/466
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
151/466
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
152/466
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
153/466
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
154/466
JVM
155/466
 Nothing to mention, so much
work went into modularisation
156/466
APIS
157/466
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");
}
}
158/466
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)
159/466
JavaDB Removal
 JavaDB was a repackaging of Apache Derby
– Relational database
– Open-source
– Entirely in Java
– Embedded JDBC driver
160/466
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
161/466
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
162/466
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));
163/466
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>
164/466
MISC
165/466
JEP-222: jshell
166/466
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
167/466
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
168/466
Java 10
2018/03/20
169/466
LANGUAGE
170/466
JEP-286: Local-variable Type
Inference
final List<String> list1 = new ArrayList<>();
System.out.println(list1);
final var list2 = new ArrayList<String>();
System.out.println(list2);
vs.
171/466
JVM
172/466
JEP-304: GC Interface
 “Improve the source code isolation of
different garbage collectors by introducing a
clean garbage collector (GC) interface.”
https://medium.com/@unmeshvjoshi/writing-your-own-garbage-collector-for-jdk12-8c83e3d0309b
https://github.com/openjdk/jdk/blob/master/src/hotspot/share/gc/shared/collectedHeap.hpp#L90
class CollectedHeap : public CHeapObj<mtGC> {
virtual jint initialize() = 0;
virtual HeapWord* allocate_new_tlab(size_t min_size,
size_t requested_size,
size_t* actual_size) = 0;
virtual HeapWord* mem_allocate(size_t size,
bool* gc_overhead_limit_was_exceeded) = 0;
// ...
173/466
JEP-307: Parallel Full GC
 Improve G1 worst-case with full parallel GC
– Before Java 9: Parallel GC
– Since Java 9: G1
https://dev.java/evolution/
174/466
JEP-310: Application Class-Data
Sharing
 Improve startup and footprint
https://www.geeksforgeeks.org/class-data-sharing-in-java/
java -XX:+UnlockCommercialFeatures-XX:+UseAppCDS
-XX:DumpLoadedClassList=LoadedClasses.1st -jar AppCDS.jar
java -XX:+UnlockCommercialFeatures -Xshare:dump -XX:+UseAppCDS
-XX:SharedClassListFile=LoadedClasses.1st
-XX:SharedArchiveFile=CustomSharedArchive.jsa -cp AppCDS.jar
java -XX:UnlockCommercialFeatures -verbose -XShare:on
-XX:+UseAppCDS -XX:SharedArchiveFile=CUstomSharedArchive.jsa
-jar AppCDS.jar
175/466
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>
176/466
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>
177/466
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
178/466
APIS
179/466
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
180/466
MISC
181/466
JEP-296: Consolidated JDK Forest
 Until Java 9
– Eight repos: root, corba, hotspot, jaxp, jaxws,
jdk, langtools, and nashorn
 Since Java 10
– One unified repository
$ROOT/jdk/src/java.base
...
$ROOT/langtools/src/java.compiler
...
182/466
JEP-296: Consolidated JDK Forest
 Until Java 9
– Eight repos: root, corba, hotspot, jaxp, jaxws,
jdk, langtools, and nashorn
 Since Java 10
– One unified repository
$ROOT/jdk/src/java.base
...
$ROOT/langtools/src/java.compiler
...
$ROOT/src/java.base
$ROOT/src/java.compiler
...
183/466
JEP-313: Native-Header Generation
Tool Removal
 javah features (and more) now in javac
javac HelloWorld.java
javah HelloWorld
javac -h jni -d bin HelloWorld.java
vs.
184/466
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
185/466
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());
186/466
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());
21.0.1+12-LTS-29
Feature: 21
Interim: 0
Update: 1
Patch: 0
Build: Optional[12]
Optional: Optional[LTS-29]
Pre: Optional.empty
187/466
Java 11
2018/09/25
188/466
LANGUAGE
189/466
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();
}
}
190/466
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);
}
}
}
191/466
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
192/466
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"));
}
}
193/466
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
194/466
JVM
195/466
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
196/466
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");
}
}
197/466
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;
}
}
198/466
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.
199/466
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
200/466
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
201/466
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
202/466
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());
203/466
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
204/466
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
205/466
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()
206/466
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
207/466
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
208/466
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
209/466
JEP-331: Low-overhead Heap
Profiling
https://docs.dynatrace.com/docs/platform-modules/applications-and-microservices/profiling-and-optimization/memory-profiling
210/466
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
211/466
APIS
212/466
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
213/466
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
214/466
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
215/466
JEP-321:
https://www.baeldung.com/java-9-http-client
final HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.version(HttpClient.Version.HTTP_2)
.timeout(Duration.ofSeconds(10))
.header("key1", "value1")
.header("key2", "value2")
.GET()
.build();
final HttpClient client = HttpClient.newHttpClient();
final HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
216/466
JEP-321:
https://www.baeldung.com/java-9-http-client
final HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.version(HttpClient.Version.HTTP_2)
.timeout(Duration.ofSeconds(10))
.header("key1", "value1")
.header("key2", "value2")
.GET()
.build();
final HttpClient client = HttpClient.newHttpClient();
final HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
{
"args": {},
"headers": {
"x-forwarded-proto": "https",
"x-forwarded-port": "443",
"host": "postman-echo.com",
"x-amzn-trace-id": "Root=1-660163f4-038cfd7075f93fad1e79f19e",
"key1": "value1",
"key2": "value2",
"user-agent": "Java-http-client/21.0.1"
},
"url": "https://postman-echo.com/get"
}
217/466
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
218/466
JEP-335: Nashorn Deprecation
 Since Java 8
– JEP-174
 ECMAScript changes rapidly
– Language
– APIs
 Maintenance challenges
– Deprecate Nashorn, its APIs, and jjs
219/466
MISC
220/466
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
221/466
JEP-328: Flight Recorder
https://www.baeldung.com/java-flight-recorder-monitoring
222/466
JEP-330: Single-file Source-code
Programs Launching
 Lower the (early) learning curve
– But no dependency management
java –cp some.jar HelloWorld.java
223/466
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
224/466
Java 12
2019/03/19
225/466
LANGUAGE
226/466
 Nothing to mention?
227/466
JVM
228/466
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>
229/466
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>
230/466
APIS
231/466
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);
}
}
232/466
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]
233/466
MISC
234/466
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
235/466
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
236/466
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
237/466
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
238/466
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
239/466
Java 13
2019/09/17
2019/09/17
2019/09/17
2019/09/17
240/466
LANGUAGE
241/466
 Nothing to mention?
242/466
JVM
243/466
JEP-351: Unused Memory
Uncommit
 ZGC automatically returns heap memory to
the operating system when idle
– Cf. JEP-346
-XX:ZUncommitDelay=<seconds>
244/466
APIS
245/466
JEP-353: Legacy Socket API
Reimplementation
 Reimplementations
– java.net.Socket
– java.net.ServerSocket
 Simpler, modern
 Easier to maintain, debug
 Ready for user-mode threads
– Fibers, Project Loom
246/466
MISC
247/466
 Nothing to mention?
248/466
Java 14
2020/03/17
249/466
LANGUAGE
250/466
-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();
}
}
251/466
-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)
252/466
-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)
253/466
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;
}
254/466
JVM
255/466
JEP-345: NUMA-Aware Memory
Allocation
 NUMA-aware memory
allocation to increase
G1 performance
– Non-uniform memory
access
– Multi-socket computers
• E.g., HP Z820
-XX:UseParallelGC=<true|false>
256/466
JEP-345: NUMA-Aware Memory
Allocation
 NUMA-aware memory
allocation to increase
G1 performance
– Non-uniform memory
access
– Multi-socket computers
• E.g., HP Z820
-XX:UseParallelGC=<true|false>
Two CPUs, with
their own DIMMs
257/466
JEP-363: Concurrent Mark Sweep
GC Removal
 Since Java 9
– Deprecated CMS
 Reduce maintenance costs
– Replaced by G1
– Two new GCs
• ZGC
• Shenandoah
258/466
APIS
259/466
JEP-352: Non-volatile Mapped Byte
Buffers
 FileChannel can create MappedByteBuffer
that access non-volatile memory
– Cf. JEP-316
https://mashona.io/blog/2020/03/17/using-jep-352-api
final File file = new File("/path/to/some/file");
final FileChannel fileChannel = (FileChannel) Files.newByteChannel(file.toPath(),
EnumSet.of(StandardOpenOption.READ,
StandardOpenOption.WRITE,
StandardOpenOption.CREATE));
try {
final MappedByteBuffer mappedByteBuffer =
fileChannel.map(MapMode.READ_WRITE, position, size);
// ...
} catch (final IOException e) {
// ...
}
260/466
MISC
261/466
JEP-349: JFR Event Streaming
 API for the streaming of JFR data
– In-process, out-of-process programs
– Cf. JEP-328
 Example: Health Report
https://blogs.oracle.com/javamagazine/post/java-flight-recorder-and-jfr-event-streaming-in-java-14
https://github.com/flight-recorder/health-report
java -javaagent:health-report.jar com.example.MyProgram
262/466
JEP-349: JFR Event Streaming
 Example: Health Report
https://blogs.oracle.com/javamagazine/post/java-flight-recorder-and-jfr-event-streaming-in-java-14
https://github.com/flight-recorder/health-report
=================== HEALTH REPORT === 2021-05-13 23:57:50 ====================
| GC: G1Old/G1New Phys. memory: 28669 MB Alloc Rate: 8 MB/s |
| OC Count : 28 Initial Heap: 448 MB Total Alloc: 190 MB |
| OC Pause Avg: 40.1 ms Used Heap : 19 MB Thread Count: 20.0 |
| OC Pause Max: 48.8 ms Commit. Heap: 47 MB Class Count : 3894.0 |
| YC Count : 8 CPU Machine : 20.12 % Safepoints: 335 |
| YC Pause Avg: 5.7 ms CPU JVM User : 10.28 % Max Safepoint: 46.4 ms |
| YC Pause Max: 22.4 ms CPU JVM System: 1.07 % Max Comp. Time: 728.3 ms |
|--- Top Allocation Methods ------------------------------- -----------------|
| DataBufferInt.(int) 11.27 % |
| Component.size() 9.01 % |
| BufferedContext.validate(...) 6.21 % |
| Path2D$Double.(...) 5.87 % |
| SunGraphics2D.clone() 5.85 % |
|--- Hot Methods ------------------------------------------------------------|
| DRenderer._endRendering(int, int) 51.11 % |
| DRenderer.copyAARow(...) 6.67 % |
| Arrays.fill(...) 4.44 % |
| StringConcatFactory.doStringConcat(...) 2.22 % |
| MarlinTileGenerator.getAlphaNoRLE(...) 2.22 % |
==============================================================================
263/466
Java 15
2020/09/15
264/466
LANGUAGE
265/466
JEP-371: Hidden Classes
 Classes
– Member classes
 Methods
– Inner classes
– Anonymous classes
– Lambda expressions
 Encapsulation
 Reflection
266/466
JEP-371: Hidden Classes
 Hidden classes
– Dynamic class creation (and their instances)
– Classes that are not publicly visible/accessible
 Improve
– Encapsulation
• Internal implementations
– Security
• Risk of unauthorized access (or tampering)
https://www.javacodegeeks.com/2024/02/explore-java-15s-hidden-classes-with-code-examples.html
267/466
JEP-371: Hidden Classes
class TopLevelClass {
public class MemberClass {
}
}
public class Example1 {
public static void main(final String[] args) throws ClassNotFoundException {
class InnerClass {
}
final InnerClass innerClass = new InnerClass();
final Callable<String> anonynmousClass = new Callable<String>() {
@Override
public String call() throws Exception { return null; }};
final Callable<String> lambdaExpression = () -> null;
final Class<?> classOfClazz = Class.forName("[...].TopLevelClass");
InfoPrinter.printInfo(classOfClazz);
final Class<?> classOfMemberClass = Class.forName("[...].TopLevelClass$MemberClass");
InfoPrinter.printInfo(classOfMemberClass);
final Class<?> classOfInnerClass = innerClass.getClass();
// final Class<?> classOfInnerClass = Class.forName("[...].Example1$1InnerClass");
InfoPrinter.printInfo(classOfInnerClass);
final Class<?> classOfAnonymousClass = anonynmousClass.getClass();
// final Class<?> classOfAnonymousClass = Class.forName("[...].Example1$1");
InfoPrinter.printInfo(classOfAnonymousClass);
final Class<?> classOfLambdaExpression = lambdaExpression.getClass();
// final Class<?> classOfLambdaExpression = Class.forName("[...].Example1$$Lambda/???");
InfoPrinter.printInfo(classOfLambdaExpression);
}
}
268/466
JEP-371: Hidden Classes
class TopLevelClass {
public class MemberClass {
}
}
public class Example1 {
public static void main(final String[] args) throws ClassNotFoundException {
class InnerClass {
}
final InnerClass innerClass = new InnerClass();
final Callable<String> anonynmousClass = new Callable<String>() {
@Override
public String call() throws Exception { return null; }};
final Callable<String> lambdaExpression = () -> null;
final Class<?> classOfClazz = Class.forName("[...].TopLevelClass");
InfoPrinter.printInfo(classOfClazz);
final Class<?> classOfMemberClass = Class.forName("[...].TopLevelClass$MemberClass");
InfoPrinter.printInfo(classOfMemberClass);
final Class<?> classOfInnerClass = innerClass.getClass();
// final Class<?> classOfInnerClass = Class.forName("[...].Example1$1InnerClass");
InfoPrinter.printInfo(classOfInnerClass);
final Class<?> classOfAnonymousClass = anonynmousClass.getClass();
// final Class<?> classOfAnonymousClass = Class.forName("[...].Example1$1");
InfoPrinter.printInfo(classOfAnonymousClass);
final Class<?> classOfLambdaExpression = lambdaExpression.getClass();
// final Class<?> classOfLambdaExpression = Class.forName("[...].Example1$$Lambda/???");
InfoPrinter.printInfo(classOfLambdaExpression);
}
}
class net.ptidej.newjava.hiddenclasses.TopLevelClass
Canonical name: net.ptidej.newjava.hiddenclasses.TopLevelClass
Name: net.ptidej.newjava.hiddenclasses.TopLevelClass
isHidden? false
class net.ptidej.newjava.hiddenclasses.TopLevelClass$MemberClass
Canonical name: net.ptidej.newjava.hiddenclasses.TopLevelClass.MemberClass
Name: net.ptidej.newjava.hiddenclasses.TopLevelClass$MemberClass
isHidden? false
class net.ptidej.newjava.hiddenclasses.Example1$1InnerClass
Canonical name: null
Name: net.ptidej.newjava.hiddenclasses.Example1$1InnerClass
isHidden? false
class net.ptidej.newjava.hiddenclasses.Example1$1
Canonical name: null
Name: net.ptidej.newjava.hiddenclasses.Example1$1
isHidden? false
class net.ptidej.newjava.hiddenclasses.Example1$$Lambda/0x0000020a81000400
Canonical name: null
Name: net.ptidej.newjava.hiddenclasses.Example1$$Lambda/0x0000020a81000400
isHidden? true
269/466
JEP-371: Hidden Classes
class TopLevelClass {
public class MemberClass {
}
}
public class Example1 {
public static void main(final String[] args) throws ClassNotFoundException {
class InnerClass {
}
final InnerClass innerClass = new InnerClass();
final Callable<String> anonynmousClass = new Callable<String>() {
@Override
public String call() throws Exception { return null; }};
final Callable<String> lambdaExpression = () -> null;
final Class<?> classOfClazz = Class.forName("[...].TopLevelClass");
InfoPrinter.printInfo(classOfClazz);
final Class<?> classOfMemberClass = Class.forName("[...].TopLevelClass$MemberClass");
InfoPrinter.printInfo(classOfMemberClass);
final Class<?> classOfInnerClass = innerClass.getClass();
// final Class<?> classOfInnerClass = Class.forName("[...].Example1$1InnerClass");
InfoPrinter.printInfo(classOfInnerClass);
final Class<?> classOfAnonymousClass = anonynmousClass.getClass();
// final Class<?> classOfAnonymousClass = Class.forName("[...].Example1$1");
InfoPrinter.printInfo(classOfAnonymousClass);
final Class<?> classOfLambdaExpression = lambdaExpression.getClass();
// final Class<?> classOfLambdaExpression = Class.forName("[...].Example1$$Lambda/???");
InfoPrinter.printInfo(classOfLambdaExpression);
}
}
class net.ptidej.newjava.hiddenclasses.TopLevelClass
Canonical name: net.ptidej.newjava.hiddenclasses.TopLevelClass
Name: net.ptidej.newjava.hiddenclasses.TopLevelClass
isHidden? false
class net.ptidej.newjava.hiddenclasses.TopLevelClass$MemberClass
Canonical name: net.ptidej.newjava.hiddenclasses.TopLevelClass.MemberClass
Name: net.ptidej.newjava.hiddenclasses.TopLevelClass$MemberClass
isHidden? false
class net.ptidej.newjava.hiddenclasses.Example1$1InnerClass
Canonical name: null
Name: net.ptidej.newjava.hiddenclasses.Example1$1InnerClass
isHidden? false
class net.ptidej.newjava.hiddenclasses.Example1$1
Canonical name: null
Name: net.ptidej.newjava.hiddenclasses.Example1$1
isHidden? false
class net.ptidej.newjava.hiddenclasses.Example1$$Lambda/0x0000020a81000400
Canonical name: null
Name: net.ptidej.newjava.hiddenclasses.Example1$$Lambda/0x0000020a81000400
isHidden? true
Hidden class
270/466
JEP-371: Hidden Classes
 Use and features of hidden classes
final InputStream stream = new FileInputStream(new File("rsc/HiddenClass.class"));
final byte[] bytes = IOUtils.toByteArray(stream);
final MethodHandles.Lookup lookup = MethodHandles.lookup();
final Class<?> hiddenClassClass1 = lookup.defineHiddenClass(bytes, true, STRONG).lookupClass();
InfoPrinter.printInfo(hiddenClassClass1);
final Class<?> notHiddenClassClass1 = lookup.defineClass(bytes);
InfoPrinter.printInfo(notHiddenClassClass1);
final Class<?> notHiddenClassClass2 = myClassLoader.loadClass("[...].HiddenClass", bytes);
InfoPrinter.printInfo(notHiddenClassClass2);
final Class<?> hiddenClassClass2 = Class.forName(hiddenClassClass1.getName());
InfoPrinter.printInfo(hiddenClassClass2);
final Class<?> hiddenClassClass3 = lookup.findClass(hiddenClassClass1.getName());
InfoPrinter.printInfo(hiddenClassClass3);
271/466
JEP-371: Hidden Classes
 Use and features of hidden classes
final InputStream stream = new FileInputStream(new File("rsc/HiddenClass.class"));
final byte[] bytes = IOUtils.toByteArray(stream);
final MethodHandles.Lookup lookup = MethodHandles.lookup();
final Class<?> hiddenClassClass1 = lookup.defineHiddenClass(bytes, true, STRONG).lookupClass();
InfoPrinter.printInfo(hiddenClassClass1);
final Class<?> notHiddenClassClass1 = lookup.defineClass(bytes);
InfoPrinter.printInfo(notHiddenClassClass1);
final Class<?> notHiddenClassClass2 = myClassLoader.loadClass("[...].HiddenClass", bytes);
InfoPrinter.printInfo(notHiddenClassClass2);
final Class<?> hiddenClassClass2 = Class.forName(hiddenClassClass1.getName());
InfoPrinter.printInfo(hiddenClassClass2);
final Class<?> hiddenClassClass3 = lookup.findClass(hiddenClassClass1.getName());
InfoPrinter.printInfo(hiddenClassClass3);
class net.ptidej.newjava.hiddenclasses.HiddenClass/0x000001e2900082b0
Canonical name: null
Name: net.ptidej.newjava.hiddenclasses.HiddenClass/0x000001e2900082b0
isHidden? true
class net.ptidej.newjava.hiddenclasses.HiddenClass
Canonical name: net.ptidej.newjava.hiddenclasses.HiddenClass
Name: net.ptidej.newjava.hiddenclasses.HiddenClass
isHidden? false
class net.ptidej.newjava.hiddenclasses.HiddenClass
Canonical name: net.ptidej.newjava.hiddenclasses.HiddenClass
Name: net.ptidej.newjava.hiddenclasses.HiddenClass
isHidden? false
As expected, the hidden class cannot be discovered!
As expected, the hidden class cannot be discovered!
272/466
JEP-371: Hidden Classes
 Use and features of hidden classes
final InputStream stream = new FileInputStream(new File("rsc/HiddenClass.class"));
final byte[] bytes = IOUtils.toByteArray(stream);
final MethodHandles.Lookup lookup = MethodHandles.lookup();
final Class<?> hiddenClassClass1 = lookup.defineHiddenClass(bytes, true, STRONG).lookupClass();
InfoPrinter.printInfo(hiddenClassClass1);
final Class<?> notHiddenClassClass1 = lookup.defineClass(bytes);
InfoPrinter.printInfo(notHiddenClassClass1);
final Class<?> notHiddenClassClass2 = myClassLoader.loadClass("[...].HiddenClass", bytes);
InfoPrinter.printInfo(notHiddenClassClass2);
final Class<?> hiddenClassClass2 = Class.forName(hiddenClassClass1.getName());
InfoPrinter.printInfo(hiddenClassClass2);
final Class<?> hiddenClassClass3 = lookup.findClass(hiddenClassClass1.getName());
InfoPrinter.printInfo(hiddenClassClass3);
class net.ptidej.newjava.hiddenclasses.HiddenClass/0x000001e2900082b0
Canonical name: null
Name: net.ptidej.newjava.hiddenclasses.HiddenClass/0x000001e2900082b0
isHidden? true
class net.ptidej.newjava.hiddenclasses.HiddenClass
Canonical name: net.ptidej.newjava.hiddenclasses.HiddenClass
Name: net.ptidej.newjava.hiddenclasses.HiddenClass
isHidden? false
class net.ptidej.newjava.hiddenclasses.HiddenClass
Canonical name: net.ptidej.newjava.hiddenclasses.HiddenClass
Name: net.ptidej.newjava.hiddenclasses.HiddenClass
isHidden? false
As expected, the hidden class cannot be discovered!
As expected, the hidden class cannot be discovered!
Hidden classes
are truly hidden
273/466
JEP-378: Text Blocks
 Multi-line string literal
– C++
• Compiler concatenates adjacent string literals
• Escape embedded (invisible) newline chars
– JavaScript
• Template literals with ` (backtick)
– Python
• Use """
274/466
JEP-378: Text Blocks
 Three quotes
– Followed by white space(s)
– Followed by a new line!
final String textBlock = """
Hello
World!""";
System.out.println(textBlock);
275/466
JEP-378: Text Blocks
 Three quotes
– Followed by white space(s)
– Followed by a new line!
final String textBlock = """
Hello
World!""";
System.out.println(textBlock);
Hello
World!
276/466
JVM
277/466
JEP-377: Scalable Low-latency GC
 Since Java 11
– Pause times not exceeding 10ms
• With 2 MB or 2 TB heaps
– Cf. JEP-333
 ZGC becomes a product feature
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
278/466
JEP-379: Low-pause-time GC
 Since Java 12
– Consistent pause times
• With 200 MB or 200 GB heaps
– Cf. JEP-189
 Shenandoah becomes a product feature
XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC
279/466
APIS
280/466
JEP-373: Legacy DatagramSocket
API Reimplementation
 Reimplementations
– java.net.DatagramSocket
– java.net.MulticastSocket
 Since Java 1.0!
 Concurrency issues
 No clean support of IPv6
 Mix of legacy Java and C code
281/466
JEP-385: RMI Object Activation
Deprecation
 Since Java 1.1
– Remote Method Invocation
 Since Java 1.2
– A remote object can be made persistent
and later activated into a live object
 Since Java 8
– Optional
– Obsolete
• Security
282/466
MISC
283/466
 Nothing to mention?
284/466
Java 16
2021/03/16
285/466
LANGUAGE
286/466
JEP-390: Warnings for Value-based
Classes
 Value-based Classes
– Marked with the final modifier
– Equal solely based on equals()
– Freely substitutable when equal
– Instantiated via factory methods
 With @ValueBased
– Warning with identity-sensitive operations
• Synchronisation, identity hashing, serialization…
https://dzone.com/articles/moving-toward-inline-classes-jep-390-and-the-value
287/466
JEP-394: Pattern Matching for
instanceof
 Testing if an expression is of a type and
conditionally extracting components
https://openjdk.org/jeps/394
final Object o1 = Integer.valueOf(1);
if (o1 instanceof Integer) {
final Integer integer = (Integer) o1;
System.out.println(integer.intValue());
}
public final boolean equals1(final Object o) {
return (o instanceof String)
&& ((String) o).equalsIgnoreCase(string);
}
288/466
JEP-394: Pattern Matching for
instanceof
 Testing if an expression is of a type and
conditionally extracting components
https://openjdk.org/jeps/394
final Object o1 = Integer.valueOf(1);
if (o1 instanceof Integer) {
final Integer integer = (Integer) o1;
System.out.println(integer.intValue());
}
public final boolean equals1(final Object o) {
return (o instanceof String)
&& ((String) o).equalsIgnoreCase(string);
}
final Object o3 = Integer.valueOf(3);
if (o3 instanceof Integer integer) {
System.out.println(integer.intValue());
}
public final boolean equals2(final Object o) {
return (o instanceof String s)
&& s.equalsIgnoreCase(string);
}
289/466
JEP-395: Records
 Nominal tuples, with immutable data
– private final
– No setters
https://www.baeldung.com/java-record-keyword
record Person(String firstName, String lastName) {
}
// ...
final Person person1 = new Person("Rick", "Deckard");
System.out.println(person1);
final Person person2 = new Person("Rick", "Deckard");
System.out.println(person2);
final Person person3 = new Person("Roy", "Batty");
System.out.println(person3);
System.out.print(person1.firstName());
System.out.println(person1.equals(person2));
System.out.println(person1.equals(person3));
final Class<?> clazz = Class.forName("[...].Person");
final Field field = clazz.getDeclaredField("firstName");
field.set(person1, "Leon");
290/466
JEP-395: Records
 Nominal tuples, with immutable data
– private final
– No setters
https://www.baeldung.com/java-record-keyword
record Person(String firstName, String lastName) {
}
// ...
final Person person1 = new Person("Rick", "Deckard");
System.out.println(person1);
final Person person2 = new Person("Rick", "Deckard");
System.out.println(person2);
final Person person3 = new Person("Roy", "Batty");
System.out.println(person3);
System.out.print(person1.firstName());
System.out.println(person1.equals(person2));
System.out.println(person1.equals(person3));
final Class<?> clazz = Class.forName("[...].Person");
final Field field = clazz.getDeclaredField("firstName");
field.set(person1, "Leon");
IllegalAccessException
291/466
JVM
292/466
JEP-347: C++14 Language Features
 Use of C++14 in JDK C++ source code
– Since Java 11
• C++ updated for recent C++ compilers
– Until Java 15
• C++98/03
 Specifics depend on the compiler
/std:c++14
-std=c++14
293/466
JEP-376: Concurrent Thread-stack
Processing
 ZGC thread-stack processing
– From safepoints to concurrent
 Remove GC pauses and scalability issues
 Make pauses sub-milliseconds
294/466
APIS
295/466
 Nothing to mention?
296/466
MISC
297/466
JEP-392: Packaging Tool
 Since Java 14
– Native Java installer generator
– Cf. JEP-343
 From WORA to WORADA
– Write Once, Run Anywhere
– Write Once, Run Anywhere, Deploy Anywhere
https://jfrog.com/blog/java-artifacts-just-got-better-jpackage-is-production-ready-in-java-16/
298/466
JEP-392: Packaging Tool
 Without JRE
 With (some of the) JRE
– Cf. JSR-376
https://jfrog.com/blog/java-artifacts-just-got-better-jpackage-is-production-ready-in-java-16/
jpackage --name myprog --input lib
--main-jar main.jar
--main-class my.program.Main
jlink --add-modules java.base,java.sql --output smalljre
jpackage --name myprog --input lib
--main-jar main.jar
--main-class my.program.Main
--runtime-image smalljre
299/466
Java 17
2021/09/14
300/466
LANGUAGE
301/466
JEP-306: Always-strict Floating-
point Semantics Restoration
 Consistently strict floating-point operations
 Before
– Platform-dependent floating-point
representations, computations
 Now
– IEEE Standard for Floating Point Arithmetic
• IEEE 754
– Warnings for unnecessary use of strictfp
302/466
JEP-409: Sealed Classes
 Fine-grain control
on subclassing
– final
– sealed
• permits
– non-sealed
sealed class Person permits Employee, Student, Instructor {
}
final class Employee extends Person {
}
sealed class Student extends Person permits Bacc, Grad {
}
final class Bacc extends Student {
}
final class Grad extends Student {
}
non-sealed class Instructor extends Person {
}
class LTA extends Instructor {
}
class ETA extends Instructor {
}
class Prof extends Instructor {
}
// ...
*https://www.reddit.com/r/java/comments/inol55/does_anyone_else_not_like_the_nonsealed_keyword/
but read also https://openjdk.org/jeps/8223002
303/466
JEP-409: Sealed Classes
 Fine-grain control
on subclassing
– final
– sealed
• permits
– non-sealed
sealed class Person permits Employee, Student, Instructor {
}
final class Employee extends Person {
}
sealed class Student extends Person permits Bacc, Grad {
}
final class Bacc extends Student {
}
final class Grad extends Student {
}
non-sealed class Instructor extends Person {
}
class LTA extends Instructor {
}
class ETA extends Instructor {
}
class Prof extends Instructor {
}
// ...
Ugly because
negative and
hyphenated*
*https://www.reddit.com/r/java/comments/inol55/does_anyone_else_not_like_the_nonsealed_keyword/
but read also https://openjdk.org/jeps/8223002
304/466
JVM
305/466
 Nothing to mention?
306/466
APIS
307/466
JEP-356: Enhanced Pseudo-random
Number Generators
https://www.baeldung.com/java-17-random-number-generators
308/466
JEP-356: Enhanced Pseudo-random
Number Generators
 Beware of thread-safety!
RandomGeneratorFactory.all().sorted(
Comparator.comparing(RandomGeneratorFactory::name))
.forEach(factory -> System.out.println(
String.format("%st%st%st%s",
factory.group(),
factory.name(),
factory.isJumpable(),
factory.isSplittable())));
final RandomGenerator generator = RandomGenerator.getDefault();
System.out.println(generator.nextInt());
309/466
JEP-398: Applet API Deprecation
 No more support in Web browsers
 Deprecated for removal
– java.applet.Applet
– java.applet.AppletStub
– java.applet.AppletContext
– java.applet.AudioClip
– javax.swing.JApplet
– java.beans.AppletInitializer
310/466
JEP-415: Context-specific
Deserialization Filters
 Context-specific, dynamically-selected
deserialization filters
-Djdk.serialFilter=net.ptidej.newjava.*;!*
final ObjectInputFilter filter =
ObjectInputFilter.Config.createFilter("net.ptidej.newjava.*;!*");
ObjectInputFilter.Config.setSerialFilter(filter);
OR
311/466
MISC
312/466
 Nothing to mention?
313/466
Java 18
2022/03/22
314/466
LANGUAGE
315/466
JEP-421: Finalization
Deprecation
 Since Java 1.0
– finalize() method
– E.g., in Caffeine (ASE’02)
 Deprecation, disable, removal
 Should be replaced with
– try with resources
• Cf. Java 7
– Cleaners
316/466
JEP-421: Finalization
Deprecation
 Since Java 9
– java.lang.ref.Cleaner
– Cleanup actions for groups of objects
https://howtodoinjava.com/java/basics/java-cleaners/
public static void main(final String[] args) throws Exception {
try (final ResourceAccessingClass o = new ResourceAccessingClass()) {
// Safely use the resource
o.businessOperation1();
o.businessOperation2();
}
}
317/466
JEP-421: Finalization
Deprecation
 Since Java 9
– java.lang.ref.Cleaner
– Cleanup actions for groups of objects
https://howtodoinjava.com/java/basics/java-cleaners/
public static void main(final String[] args) throws Exception {
try (final ResourceAccessingClass o = new ResourceAccessingClass()) {
// Safely use the resource
o.businessOperation1();
o.businessOperation2();
}
}
Inside businessOperation1() with [...].Resource@65b54208
Inside businessOperation2() with [...].Resource@65b54208
Resource cleaned up
318/466
JEP-421: Finalization
Deprecation
class Resource {
// Some (expensive) resource
}
class ResourceAccessingClass implements AutoCloseable {
private final Cleaner cleaner = Example1.getCleaner();
private final Cleaner.Cleanable cleanable;
private final Resource resource;
public ResourceAccessingClass() {
this.resource = new Resource();
this.cleanable = cleaner.register(this, () -> {
System.out.println("Resource cleaned up");});
}
public void businessOperation1() {
System.out.print("Inside businessOperation1() with ");
System.out.println(this.resource);
}
// ...
https://howtodoinjava.com/java/basics/java-cleaners/
319/466
JEP-421: Finalization
Deprecation
class Resource {
// Some (expensive) resource
}
class ResourceAccessingClass implements AutoCloseable {
private final Cleaner cleaner = Example1.getCleaner();
private final Cleaner.Cleanable cleanable;
private final Resource resource;
public ResourceAccessingClass() {
this.resource = new Resource();
this.cleanable = cleaner.register(this, () -> {
System.out.println("Resource cleaned up");});
}
public void businessOperation1() {
System.out.print("Inside businessOperation1() with ");
System.out.println(this.resource);
}
// ...
https://howtodoinjava.com/java/basics/java-cleaners/
Register a Cleanable to
clean asynchronously
320/466
JVM
321/466
 Nothing to mention?
322/466
APIS
323/466
JEP-400: UTF-8 by Default
 UTF-8 by default
 Consistent behaviour
– Implementations
– Operating systems
– Locales
 Except for console I/O
https://en.wikipedia.org/wiki/UTF-8
Declared character set for the 10 million
most popular websites, since 2010
324/466
JEP-408: Simple Web Server
 Command-line tool
– Different from JEP-321
 Minimal Web server
– Static files only
– No CGI or servlets
https://www.baeldung.com/simple-web-server-java-18
jwebserver -d /opt
Binding to loopback by default.
For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving /opt and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/
325/466
JEP-408: Simple Web Server
final InetSocketAddress address = new InetSocketAddress(8080);
final Path path1 = Path.of("D:DocumentsTutorials220926 - New Java");
final HttpServer server = SimpleFileServer.createFileServer(address, path1,
SimpleFileServer.OutputLevel.VERBOSE);
final Path path2 = Path.of("D:DocumentsTutorials220926 - New JavaWorkspace");
final HttpHandler handler1 = SimpleFileServer.createFileHandler(path2);
server.createContext("/test1", handler1);
final HttpHandler allowedResponse = HttpHandlers.of(200, Headers.of("Allow", "GET"), "Welcome");
final HttpHandler deniedResponse = HttpHandlers.of(401, Headers.of("Deny", "GET"), "Denied");
final Predicate<Request> findAllowedPath = r -> r.getRequestURI().getPath().equals("/test2/allowed");
final HttpHandler handler2 = HttpHandlers.handleOrElse(findAllowedPath, allowedResponse, deniedResponse);
server.createContext("/test2", handler2);
server.start();
https://www.baeldung.com/simple-web-server-java-18
326/466
JEP-416: Reflection with
Method Handles
 Since Java 1.0
– sun.reflect.DelegatingMethodAccessorImpl
– jdk.internal.reflect.DelegatingMethod
AccessorImpl
 Inflating implementation
– First, native code
– Then, dynamically-generated byte code
• With some uses of sun.misc.Unsafe
– Since Java 1.4
https://blogs.oracle.com/javamagazine/post/java-reflection-method-handles
327/466
JEP-416: Reflection with
Method Handles
 Method handles ≈ Reflection API
https://blogs.oracle.com/javamagazine/post/java-reflection-method-handles
int compare(final String str1, final String str2) { return 42; }
int compare(final String str, final int i) { return 24; }
public static void main(final String[] args) throws Throwable {
var lookup = MethodHandles.lookup();
var methodType1 = MethodType.methodType(int.class, String.class, String.class);
System.out.println("MethodType : " + methodType1);
var methodHandle1 = lookup.findVirtual(lookup.lookupClass(), "compare", methodType1);
System.out.println("MethodHandle: " + methodHandle1.type());
System.out.println(methodHandle1.invoke(new Example1(), "Hello", "World!"));
var methodType2 = MethodType.methodType(int.class, String.class, int.class);
var methodHandle2 = lookup.findVirtual(lookup.lookupClass(), "compare", methodType2);
System.out.println(methodHandle2.invoke(new Example1(), "Hello", 0));
}
328/466
JEP-416: Reflection with
Method Handles
 Method handles ≈ Reflection API
https://blogs.oracle.com/javamagazine/post/java-reflection-method-handles
int compare(final String str1, final String str2) { return 42; }
int compare(final String str, final int i) { return 24; }
public static void main(final String[] args) throws Throwable {
var lookup = MethodHandles.lookup();
var methodType1 = MethodType.methodType(int.class, String.class, String.class);
System.out.println("MethodType : " + methodType1);
var methodHandle1 = lookup.findVirtual(lookup.lookupClass(), "compare", methodType1);
System.out.println("MethodHandle: " + methodHandle1.type());
System.out.println(methodHandle1.invoke(new Example1(), "Hello", "World!"));
var methodType2 = MethodType.methodType(int.class, String.class, int.class);
var methodHandle2 = lookup.findVirtual(lookup.lookupClass(), "compare", methodType2);
System.out.println(methodHandle2.invoke(new Example1(), "Hello", 0));
}
Introspection, really
329/466
JEP-416: Reflection with
Method Handles
 MethodHandles.
lookup()
– Methods, fields
accessible where the
lookup object is created
– Inaccessible methods
are not visible from the
lookup context
 MethodHandle.
invoke()
– Any arguments
– Any return type
– Varags (cf. Java 7)
https://blogs.oracle.com/javamagazine/post/java-reflection-method-handles
public final native
@PolymorphicSignature
Object invoke(Object...)
throws Throwable;
330/466
JEP-416: Reflection with
Method Handles
 Method handles implement reflection
– Without changing the Reflection API!
• Since Java 1.1
– If old implementation is needed
 Less overhead
– MethodHandle.invokeWithArguments()
callable by reflection and JNI
https://blogs.oracle.com/javamagazine/post/java-reflection-method-handles
Djdk.reflect.useDirectMethodHandle=false
331/466
JEP-418: Internet-address
Resolution SPI
 Service-provider
interface (SPI) for
host name and
address resolution
 Use (module) services
– Cf. JSR-376
 java.net.InetAddress
can use resolvers
– Others than the OS
built-in resolver
• hosts file and Domain
Name System (DNS)
public sealed class InetAddress implements Serializable permits Inet4Address, Inet6Address {
private static InetAddressResolver loadResolver() {
return ServiceLoader.load(InetAddressResolverProvider.class)
.findFirst()
.map(nsp -> nsp.get(builtinConfiguration()))
.orElse(BUILTIN_RESOLVER);
}
332/466
JEP-418: Internet-address
Resolution SPI
 Service-provider
interface (SPI) for
host name and
address resolution
 Use (module) services
– Cf. JSR-376
 java.net.InetAddress
can use resolvers
– Others than the OS
built-in resolver
• hosts file and Domain
Name System (DNS)
public sealed class InetAddress implements Serializable permits Inet4Address, Inet6Address {
private static InetAddressResolver loadResolver() {
return ServiceLoader.load(InetAddressResolverProvider.class)
.findFirst()
.map(nsp -> nsp.get(builtinConfiguration()))
.orElse(BUILTIN_RESOLVER);
}
sealed class with two subclasses
ServiceLoader with default object
333/466
MISC
334/466
 Nothing to mention?
335/466
Java 19
2022/09/20
336/466
 Only previews or incubator
337/466
Java 20
2023/03/21
338/466
 Only previews or incubator
339/466
Java 21
2023/09/19
340/466
LANGUAGE
341/466
JEP-440: Record Patterns
 Since Java 16
– instanceof pattern matching
– Records
– Cf. JEP-394, JEP-395
 Record patterns for record values
342/466
JEP-440: Record Patterns
record Person(String firstName, String lastName) {
}
public class Example1 {
public static void main(final String[] args) {
final Person person1 = new Person("Rick", "Deckard");
final Person person2 = new Person("Roy", "Batty");
final Object o1 = person1;
if (o1 instanceof Person p) {
System.out.println(p.firstName());
}
final Object o2 = person2;
if (o2 instanceof final Person(final String first, final String last)) {
System.out.println(first);
}
}
}
343/466
JEP-440: Record Patterns
record Person(String firstName, String lastName) {
}
public class Example1 {
public static void main(final String[] args) {
final Person person1 = new Person("Rick", "Deckard");
final Person person2 = new Person("Roy", "Batty");
final Object o1 = person1;
if (o1 instanceof Person p) {
System.out.println(p.firstName());
}
final Object o2 = person2;
if (o2 instanceof final Person(final String first, final String last)) {
System.out.println(first);
}
}
}
Rick
Roy
344/466
JEP-441: switch Pattern Matching
final String response = "Yes";
switch (response) {
case null -> {
System.out.println("Boom!");
}
case String s when s.equalsIgnoreCase("YES") -> {
System.out.println("You got it");
}
case String s when s.equalsIgnoreCase("NO") -> {
System.out.println("Too bad");
}
case String s -> {
System.out.println("Sorry?");
}
}
345/466
JEP-441: switch Pattern Matching
final String response = "Yes";
switch (response) {
case null -> {
System.out.println("Boom!");
}
case String s when s.equalsIgnoreCase("YES") -> {
System.out.println("You got it");
}
case String s when s.equalsIgnoreCase("NO") -> {
System.out.println("Too bad");
}
case String s -> {
System.out.println("Sorry?");
}
}
You got it
346/466
JVM
347/466
JEP-439: Generational ZGC
 Since Java 15
– Z Garbage Collector (ZGC)
– Cf. JEP-377
 Separate generations for young, old objects
– More frequent collection of young objects
– Minimal manual configuration
-XX:+UseZGC -XX:+ZGenerational
348/466
APIS
349/466
JEP-431: Sequenced Collections
 Inconsistencies in the collections
– First, last elements
– Reverse order
https://www.baeldung.com/java-21-sequenced-collections
Last Element
First Element
list.get(list.size() – 1)
list.get(0)
List
deque.getLast()
deque.getFirst()
Deque
sortedSet.last()
sortedSet.first()
SortedSet
Missing
linkedHS.iterator().next()
LinkedHashSet
350/466
JEP-431: Sequenced Collections
https://www.baeldung.com/java-21-sequenced-collections
351/466
JEP-431: Sequenced Collections
https://www.baeldung.com/java-21-sequenced-collections
public interface SequencedCollection<E> extends Collection<E> {
SequencedCollection<E> reversed();
default void addFirst(E e) {
throw new UnsupportedOperationException();
}
default void addLast(E e) {
throw new UnsupportedOperationException();
}
default E getFirst() {
return this.iterator().next();
}
default E getLast() {
return this.reversed().iterator().next();
}
default E removeFirst() {
var it = this.iterator();
E e = it.next();
it.remove();
return e;
}
default E removeLast() {
var it = this.reversed().iterator();
E e = it.next();
it.remove();
return e;
}
}
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.getFirst());
System.out.println(list.getLast());
}
352/466
JEP-431: Sequenced Collections
https://www.baeldung.com/java-21-sequenced-collections
public interface SequencedCollection<E> extends Collection<E> {
SequencedCollection<E> reversed();
default void addFirst(E e) {
throw new UnsupportedOperationException();
}
default void addLast(E e) {
throw new UnsupportedOperationException();
}
default E getFirst() {
return this.iterator().next();
}
default E getLast() {
return this.reversed().iterator().next();
}
default E removeFirst() {
var it = this.iterator();
E e = it.next();
it.remove();
return e;
}
default E removeLast() {
var it = this.reversed().iterator();
E e = it.next();
it.remove();
return e;
}
}
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.getFirst());
System.out.println(list.getLast());
}
Neat use of default
methods (cf. Java 8)
353/466
JEP-431: Sequenced Collections
https://www.baeldung.com/java-21-sequenced-collections
public interface SequencedCollection<E> extends Collection<E> {
SequencedCollection<E> reversed();
default void addFirst(E e) {
throw new UnsupportedOperationException();
}
default void addLast(E e) {
throw new UnsupportedOperationException();
}
default E getFirst() {
return this.iterator().next();
}
default E getLast() {
return this.reversed().iterator().next();
}
default E removeFirst() {
var it = this.iterator();
E e = it.next();
it.remove();
return e;
}
default E removeLast() {
var it = this.reversed().iterator();
E e = it.next();
it.remove();
return e;
}
}
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.getFirst());
System.out.println(list.getLast());
}
Rick Deckard
Mary
Neat use of default
methods (cf. Java 8)
354/466
JEP-444: Virtual Threads
 Since Java 1.0
– Thread-per-request style
– Limited number of available threads
 High-throughput concurrent programs
 Virtual threads
– Lightweight threads
– Ease writing, maintaining, and observing
355/466
JEP-444: Virtual Threads
https://davidvlijmincx.com/posts/create_virtual_threads_with_project_loom/
final Runnable printThread = () -> System.out.println(Thread.currentThread());
new Thread(printThread).start();
final ThreadFactory threadFactory1 = Thread.ofPlatform().factory();
final Thread platformThread2 = threadFactory1.newThread(printThread);
platformThread2.start();
Thread.startVirtualThread(printThread);
final ThreadFactory threadFactory2 = Thread.ofVirtual().factory();
final Thread virtualThread2 = threadFactory2.newThread(printThread);
virtualThread2.start();
356/466
JEP-444: Virtual Threads
https://davidvlijmincx.com/posts/create_virtual_threads_with_project_loom/
final Runnable printThread = () -> System.out.println(Thread.currentThread());
new Thread(printThread).start();
final ThreadFactory threadFactory1 = Thread.ofPlatform().factory();
final Thread platformThread2 = threadFactory1.newThread(printThread);
platformThread2.start();
Thread.startVirtualThread(printThread);
final ThreadFactory threadFactory2 = Thread.ofVirtual().factory();
final Thread virtualThread2 = threadFactory2.newThread(printThread);
virtualThread2.start();
Thread[#20,Thread-0,5,main]
Thread[#21,Thread-1,5,main]
VirtualThread[#22]/runnable@ForkJoinPool-1-worker-1
VirtualThread[#24]/runnable@ForkJoinPool-1-worker-2
357/466
JEP-452: Key Encapsulation
Mechanism API
 Key encapsulation mechanisms (KEMs)
– Securing symmetric keys
– Using public key cryptography
 Enable programs to use KEM algorithms
 Allow implementations of KEM algorithms
– Java code
– Native code
358/466
MISC
359/466
JEP-445: Unnamed Classes and
Instance Main Methods
 Reduce barrier to entry
 Mimic scripting languages
public class Example1 {
public static void main(final String[] args) {
System.out.println("Hello, World!");
}
}
360/466
JEP-445: Unnamed Classes and
Instance Main Methods
 Reduce barrier to entry
 Mimic scripting languages
public class Example1 {
public static void main(final String[] args) {
System.out.println("Hello, World!");
}
}
void main() {
System.out.println("Hello, World!");
}
361/466
JEP-445: Unnamed Classes and
Instance Main Methods
void main() {
System.out.println("Hello, World!");
final Class clazz = this.getClass();
System.out.println(clazz.getName());
System.out.println(clazz.getPackage().getName());
System.out.println(clazz.getModule().getName());
}
Example3.java
362/466
JEP-445: Unnamed Classes and
Instance Main Methods
java --source 22 --enable-preview Example3.java
void main() {
System.out.println("Hello, World!");
final Class clazz = this.getClass();
System.out.println(clazz.getName());
System.out.println(clazz.getPackage().getName());
System.out.println(clazz.getModule().getName());
}
Example3.java
363/466
JEP-445: Unnamed Classes and
Instance Main Methods
java --source 22 --enable-preview Example3.java
void main() {
System.out.println("Hello, World!");
final Class clazz = this.getClass();
System.out.println(clazz.getName());
System.out.println(clazz.getPackage().getName());
System.out.println(clazz.getModule().getName());
}
Hello, World!
Example3
null
Example3.java
364/466
JEP-445: Unnamed Classes and
Instance Main Methods
java --source 22 --enable-preview Example3.java
void main() {
System.out.println("Hello, World!");
final Class clazz = this.getClass();
System.out.println(clazz.getName());
System.out.println(clazz.getPackage().getName());
System.out.println(clazz.getModule().getName());
}
Hello, World!
Example3
null
Example3.java
Why empty?
Why null?
365/466
JEP-445: Unnamed Classes and
Instance Main Methods
java --source 22 --enable-preview Example3.java
void main() {
System.out.println("Hello, World!");
final Class clazz = this.getClass();
System.out.println(clazz.getName());
System.out.println(clazz.getPackage().getName());
System.out.println(clazz.getModule().getName());
}
Hello, World!
Example3
null
Example3.java
Why empty?
Why null?
Using javac 22 to compile
366/466
JEP-445: Unnamed Classes and
Instance Main Methods
 Without main()
// Compiled from Example3.java (version 22 : 66.65535, super bit)
final class Example3 {
// Method descriptor #6 ()V
// Stack: 1, Locals: 1
Example3();
0 aload_0 [this]
1 invokespecial java.lang.Object()
4 return
Line numbers:
[pc: 0, line: 7]
// Method descriptor #6 ()V
// Stack: 2, Locals: 2
void main();
0 getstatic java.lang.System.out : java.io.PrintStream
3 ldc <String "Hello, World!">
5 invokevirtual java.io.PrintStream.println(java.lang.String) : void
[...]
49 return
[...]
}
Example3.java:7: error: implicitly declared class does not have
main method in the form of void main() or void main(String[] args)
367/466
JEP-445: Unnamed Classes and
Instance Main Methods
 Without main()
// Compiled from Example3.java (version 22 : 66.65535, super bit)
final class Example3 {
// Method descriptor #6 ()V
// Stack: 1, Locals: 1
Example3();
0 aload_0 [this]
1 invokespecial java.lang.Object()
4 return
Line numbers:
[pc: 0, line: 7]
// Method descriptor #6 ()V
// Stack: 2, Locals: 2
void main();
0 getstatic java.lang.System.out : java.io.PrintStream
3 ldc <String "Hello, World!">
5 invokevirtual java.io.PrintStream.println(java.lang.String) : void
[...]
49 return
[...]
}
Example3.java:7: error: implicitly declared class does not have
main method in the form of void main() or void main(String[] args)
Autogenerated
368/466
JEP-445: Unnamed Classes and
Instance Main Methods
 Without main()
// Compiled from Example3.java (version 22 : 66.65535, super bit)
final class Example3 {
// Method descriptor #6 ()V
// Stack: 1, Locals: 1
Example3();
0 aload_0 [this]
1 invokespecial java.lang.Object()
4 return
Line numbers:
[pc: 0, line: 7]
// Method descriptor #6 ()V
// Stack: 2, Locals: 2
void main();
0 getstatic java.lang.System.out : java.io.PrintStream
3 ldc <String "Hello, World!">
5 invokevirtual java.io.PrintStream.println(java.lang.String) : void
[...]
49 return
[...]
}
Example3.java:7: error: implicitly declared class does not have
main method in the form of void main() or void main(String[] args)
Autogenerated
Known by the JVM
369/466
Java 22
2024/03/19
370/466
LANGUAGE
371/466
JEP-456: Unnamed Variables and
Patterns
 Prevent unwarranted warnings
final List<Order> orders = new ArrayList<>();
int total = 0;
for (final Order o : orders) {
total++;
}
System.out.println(total);
372/466
JEP-456: Unnamed Variables and
Patterns
 Prevent unwarranted warnings
final List<Order> orders = new ArrayList<>();
int total = 0;
for (final Order o : orders) {
total++;
}
System.out.println(total);
Warning: The value of the
local variable o is not used
373/466
JEP-456: Unnamed Variables and
Patterns
 Prevent unwarranted warnings
final List<Order> orders = new ArrayList<>();
int total = 0;
for (final Order o : orders) {
total++;
}
System.out.println(total);
final List<Order> orders = new ArrayList<>();
int total = 0;
for (final Order _ : orders) {
total++;
}
System.out.println(total);
Warning: The value of the
local variable o is not used
374/466
JEP-456: Unnamed Variables and
Patterns
 Prevent unwarranted warnings
final List<Order> orders = new ArrayList<>();
int total = 0;
for (final Order o : orders) {
total++;
}
System.out.println(total);
final List<Order> orders = new ArrayList<>();
int total = 0;
for (final Order _ : orders) {
total++;
}
System.out.println(total);
Warning: The value of the
local variable o is not used
Unnamed variable
375/466
JVM
376/466
JEP-423: Region Pinning for G1
 Since Java 9
– G1
 Since Java 10
– JEP-307
 Since Java 12
– JEP-344
– JEP-346
 Since Java 14
– JEP-345
 Reduce latency with
region pinning
– GC continues even if a
critical region was created
by some JNI code
• GetPrimitiveArrayCritical,
GetStringCritical
• References to arrays or
Strings in the heap
• References held until
release functions called
377/466
JEP-454: Foreign Function and
Memory API
 Foreign Function and
Memory (FFM) API
– Productivity: replace brittle JNI
with a concise, readable, and
pure-Java API
– Performance: access to FFM
with overhead comparable to
JNI (and Unsafe)
– Support: discovery and
invocation of native libraries
on every OS with the JVM
– Uniformity: operations for
structured/unstructured data
(no matter size, kind)
– Soundness: no use-after-free
bugs, even with (de)allocations
by multiple threads
– Integrity: warning for unsafe
operations with native code
and data
https://www.infoq.com/news/2023/10/foreign-function-and-memory-api/
378/466
JEP-454: Foreign Function and
Memory API
https://www.infoq.com/news/2023/10/foreign-function-and-memory-api/
private String[] sort(final String[] strings) {
final Linker linker = Linker.nativeLinker();
final SymbolLookup stdlib = linker.defaultLookup();
final MemorySegment radixSort = stdlib.find("radixsort").orElseThrow();
final MethodHandle methodHandle = linker.downcallHandle(radixSort,
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.JAVA_INT,
ValueLayout.ADDRESS, ValueLayout.JAVA_CHAR));
try (final Arena arena = Arena.ofConfined()) {
final MemorySegment pointers = arena.allocateArray(ValueLayout.ADDRESS, strings.length);
for (int i = 0; i < strings.length; i++) {
final MemorySegment cString = arena.allocateUtf8String(strings[i]);
pointers.setAtIndex(ValueLayout.ADDRESS, i, cString);
}
methodHandle.invoke(pointers, strings.length, MemorySegment.NULL, '0’);
for (int i = 0; i < strings.length; i++) {
MemorySegment cString = pointers.getAtIndex(ValueLayout.ADDRESS, i);
cString = cString.reinterpret(Long.MAX_VALUE);
strings[i] = cString.getUtf8String(0);
}
} catch (final Throwable e) {
throw new RuntimeException(e);
}
return strings;
}
379/466
APIS
380/466
 Nothing to mention?
381/466
MISC
382/466
JEP-458: Multi-file Source-code
Programs Launching
 Lower the (early) learning curve
– But no dependency management
java –cp * Prog1.java
Prog1.java
Prog2.java
Helper.java
library1.jar
library2.jar
383/466
Java 23
2024/09/18
384/466
Disclaimer
 Lots of preview/incubating features…
Some still worth mentioning!
(With titles in italic)
385/466
LANGUAGE
386/466
JEP-445: Primitive Types in
Patterns, instanceof, and switch
 Systematic and consistent (everywhere?)
uses of pattern-matching
final int someIntValue = 42;
switch (someIntValue) {
case 0 -> System.out.println("Got 0");
case 1 -> System.out.println("Got 1");
case 2 -> System.out.println("Got 2");
case int i when i >= 100 -> System.out.println("Got " + i + " >= 100");
case int i -> System.out.println("Got " + i + " >2 and <100");
}
387/466
JEP-445: Primitive Types in
Patterns, instanceof, and switch
 Requires conversion, questions safety
boolean
double
float
long
int
Char
short
byte
To →
From ↓
—
ɛ
ɛ
ɛ
ɛ
ωη
ɛ
≈
byte
—
ɛ
ɛ
ɛ
ɛ
η
≈
η
short
—
ɛ
ɛ
ɛ
ɛ
≈
η
η
char
—
ɛ
ω
ɛ
≈
η
η
η
int
—
ω
ω
≈
η
η
η
η
long
—
ɛ
≈
η
η
η
η
η
float
—
≈
η
η
η
η
η
η
double
≈
—
—
—
—
—
—
—
boolean
388/466
JEP-482: Flexible
Constructor Bodies
 “Fail Fast”
class ValidationWithAuxiliaryMethod extends BigDecimal {
private static long checkPositive(final long value) {
if (value <= 0) throw new IllegalArgumentException("...");
return value;
}
public ValidationWithAuxiliaryMethod(final long value) {
super(checkPositive(value));
}
}
389/466
JEP-482: Flexible
Constructor Bodies
 “Fail Fast”
class ValidationWithAuxiliaryMethod extends BigDecimal {
private static long checkPositive(final long value) {
if (value <= 0) throw new IllegalArgumentException("...");
return value;
}
public ValidationWithAuxiliaryMethod(final long value) {
super(checkPositive(value));
}
}
class ValidationInConstructor extends BigInteger {
public ValidationInConstructor(final long value) {
if (value <= 0) throw new IllegalArgumentException("...");
super(value);
...
390/466
JVM
391/466
JEP-474: ZGC: Generational Mode
by Default
 What can I say?
392/466
APIS
393/466
JEP-466: Class-File API
 Manipulate class-files directly in Java
ClassFile.of().buildTo(Path.of("A.class"), ClassDesc.of("A"),
classBuilder -> classBuilder.withMethod("fooBar",
MethodTypeDesc.of(CD_void, CD_boolean, CD_int),
AccessFlags.ofMethod(AccessFlag.PUBLIC).flagsMask(),
methodBuilder -> methodBuilder.withCode(codeBuilder -> {
final Label label1 = codeBuilder.newLabel();
final Label label2 = codeBuilder.newLabel();
codeBuilder.iload(1).ifeq(label1).aload(0).iload(2)
.invokevirtual(ClassDesc.of("Foo"), "foo",
MethodTypeDesc.of(CD_void, CD_int))
.goto_(label2).labelBinding(label1).aload(0)
.iload(2)
.invokevirtual(ClassDesc.of("Foo"), "bar",
MethodTypeDesc.of(CD_void, CD_int))
.labelBinding(label2).return_();
})));
394/466
JEP-469: Vector API
 “Introduce an API to express vector
computations that reliably compile at runtime
to optimal vector instructions on supported
CPU architectures, thus achieving
performance superior to equivalent scalar
computations.”
395/466
JEP-469: Vector API
static final VectorSpecies<Float> SPECIES =
FloatVector.SPECIES_PREFERRED;
void vectorComputation(float[] a, float[] b, float[] c) {
int i = 0;
int upperBound = SPECIES.loopBound(a.length);
for (; i < upperBound; i += SPECIES.length()) {
// FloatVector va, vb, vc;
var va = FloatVector.fromArray(SPECIES, a, i);
var vb = FloatVector.fromArray(SPECIES, b, i);
var vc = va.mul(va).add(vb.mul(vb)).neg();
vc.intoArray(c, i);
}
for (; i < a.length; i++) {
c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
}
}
396/466
JEP-476: Module Import
Declarations
 Simplify the use of modules
import module M1;
public class Example1 {
...
module M1 {
exports p1;
exports p2 to M0;
exports p3 to M3;
requires transitive M4;
requires M5;
}
module M3 { ... }
module M4 {
exports p10;
}
module M5 {
exports p11;
}
397/466
JEP-476: Module Import
Declarations
 Simplify the use of modules
import module M1;
public class Example1 {
...
module M1 {
exports p1;
exports p2 to M0;
exports p3 to M3;
requires transitive M4;
requires M5;
}
module M3 { ... }
module M4 {
exports p10;
}
module M5 {
exports p11;
}
398/466
JEP-476: Module Import
Declarations
 Simplify the use of modules
import module M1;
public class Example1 {
...
module M1 {
exports p1;
exports p2 to M0;
exports p3 to M3;
requires transitive M4;
requires M5;
}
module M3 { ... }
module M4 {
exports p10;
}
module M5 {
exports p11;
}
399/466
JEP-476: Module Import
Declarations
 Simplify the use of modules
import module M1;
public class Example1 {
...
module M1 {
exports p1;
exports p2 to M0;
exports p3 to M3;
requires transitive M4;
requires M5;
}
module M3 { ... }
module M4 {
exports p10;
}
module M5 {
exports p11;
}
400/466
JEP-481: Scoped Values
 Client-dependent context
 Alternative to ThreadLocal
class Framework {
private final static ScopedValue<FrameworkContext> CONTEXT =
ScopedValue.newInstance();
void serve(Request request, Response response) {
var context = createContext(request);
ScopedValue.runWhere(CONTEXT, context,
() -> Application.handle(request, response));
}
public PersistedObject readKey(String key) {
var context = CONTEXT.get();
var db = getDBConnection(context);
db.readKey(key);
...
401/466
MISC
402/466
JEP-471: Deprecate the Memory-
Access Methods for Removal
class OffHeapArray {
private final static int BYTE_SIZE = 1;
private long size;
private long address;
public OffHeapArray(final long size) throws ... {
this.size = size;
this.address = this.getUnsafe().allocateMemory(this.size * BYTE_SIZE);
}
private Unsafe getUnsafe() throws ... {
final Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(null);
}
public void set(final long idx, final byte value) throws ... {
this.getUnsafe().putByte(this.address + idx * BYTE_SIZE, value);
}
public int get(final long idx) throws ... {
return this.getUnsafe().getByte(this.address + idx * BYTE_SIZE);
}
public void freeMemory() throws ... {
this.getUnsafe().freeMemory(this.address);
}
...
403/466
JEP-471: Deprecate the Memory-
Access Methods for Removal
final OffHeapArray oha =
new OffHeapArray(3);
oha.set(0, (byte) 42);
oha.set(1, (byte) 84);
oha.set(2, (byte) 111);
System.out.println(oha.get(0));
System.out.println(oha.get(1));
System.out.println(oha.get(2));
oha.freeMemory();
404/466
JEP-471: Deprecate the Memory-
Access Methods for Removal
final OffHeapArray oha =
new OffHeapArray(3);
oha.set(0, (byte) 42);
oha.set(1, (byte) 84);
oha.set(2, (byte) 111);
System.out.println(oha.get(0));
System.out.println(oha.get(1));
System.out.println(oha.get(2));
oha.freeMemory();
final OffHeapArray oha =
new OffHeapArray(1);
oha.set(0, (byte) 42);
oha.set(1, (byte) 84);
oha.set(2, (byte) 111);
System.out.println(oha.get(0));
System.out.println(oha.get(1));
System.out.println(oha.get(2));
oha.freeMemory();
Where am I writing?
405/466
JEP-477: Implicitly Declared Classes
and Instance Main Methods
 Java Python-isation
continues…
– “thereby avoiding the
mysterious
System.out.println”
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
406/466
JEP-477: Implicitly Declared Classes
and Instance Main Methods
 Java Python-isation
continues…
– “thereby avoiding the
mysterious
System.out.println”
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
class HelloWorld {
void main() {
System.out.println("Hello, World!");
}
}
407/466
JEP-477: Implicitly Declared Classes
and Instance Main Methods
 Java Python-isation
continues…
– “thereby avoiding the
mysterious
System.out.println”
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
class HelloWorld {
void main() {
System.out.println("Hello, World!");
}
}
void main() {
System.out.println("Hello, World!");
}
408/466
JEP-477: Implicitly Declared Classes
and Instance Main Methods
 Java Python-isation
continues…
– “thereby avoiding the
mysterious
System.out.println”
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
class HelloWorld {
void main() {
System.out.println("Hello, World!");
}
}
void main() {
println("Hello, World!");
}
void main() {
System.out.println("Hello, World!");
}
409/466
Java 24
2025/03/18
410/466
LANGUAGE
411/466
Language
 Some preview features…
Some still worth mentioning!
412/466
Language
 JEP-487: Scoped Values
– Fourth Preview
 JEP-488: Primitive Types in Patterns,
instanceof, and switch
– Second Preview
 JEP-492: Flexible Constructor Bodies
– Third Preview
 JEP-494: Module Import Declarations
– Second Preview
413/466
JVM
414/466
JEP-475: Late Barrier Expansion for G1
 Reduces overall JVM overhead
– For optimising JIT compilers, e.g., JDK’s C2
 Expanding G1 barriers early increases C2
overhead by 10-20%
415/466
JEP-475: Late Barrier Expansion for G1
416/466
JEP-475: Late Barrier Expansion for G1
417/466
JEP-490: ZGC: Remove the Non-
Generational Mode
 Remove the non-generational mode

418/466
JEP-490: ZGC: Remove the Non-
Generational Mode
 Remove the non-generational mode
 What can I say?
419/466
JEP-483: Ahead-of-Time Class
Loading and Linking
 Most applications start up follow the same
steps every time they run
 Extend the HotSpot JVM to support an
ahead-of-time cache
– Evolution of class-data sharing
420/466
JEP-483: Ahead-of-Time Class
Loading and Linking
 Requires three steps
– Training run
– Cache creation
– Cache utilisation
$ java -cp bin/ net.ptidej.newjava.aotcache.Main
Some application doing lots of things at start up...
$ java -
-
-
-XX:AOTMode=record
XX:AOTMode=record
XX:AOTMode=record
XX:AOTMode=record -
-
-
-XX:AOTConfiguration=app.aotconf
XX:AOTConfiguration=app.aotconf
XX:AOTConfiguration=app.aotconf
XX:AOTConfiguration=app.aotconf 
-cp bin/ net.ptidej.newjava.aotcache.Main
Some application doing lots of things at start up...
$ java -
-
-
-XX:AOTMode=create
XX:AOTMode=create
XX:AOTMode=create
XX:AOTMode=create -
-
-
-XX:AOTConfiguration=app.aotconf
XX:AOTConfiguration=app.aotconf
XX:AOTConfiguration=app.aotconf
XX:AOTConfiguration=app.aotconf -
-
-
-XX:AOTCache=app.aot
XX:AOTCache=app.aot
XX:AOTCache=app.aot
XX:AOTCache=app.aot 
-cp bin/ net.ptidej.newjava.aotcache.Main
[0.237s][warning][cds] Skipping net/.../Main: Unsupported location
AOTCache creation is complete: app.aot
$ java -
-
-
-XX:AOTCache=app.aot
XX:AOTCache=app.aot
XX:AOTCache=app.aot
XX:AOTCache=app.aot -cp bin/ net.ptidej.newjava.aotcache.Main
Some application doing lots of things at start up...
421/466
JEP-483: Ahead-of-Time Class
Loading and Linking
 Creates two new files
– An AOT file
• Very large, binary file
• Classes are available instantly from it
– An AOT configuration file
• Text file
$ java -cp bin/ net.ptidej.newjava.aotcache.Main
Some application doing lots of things at start up...
$ ll
total 4.1M
-r--r--r-- 1 yann None 9.0M
9.0M
9.0M
9.0M Mar 19 22:10 app.aot
-rw-r--r-- 1 yann None 42K
42K
42K
42K Mar 19 22:09 app.aotconf
drwxr-xr-x 1 yann None 0 Mar 19 22:08 bin/
drwxr-xr-x 1 yann None 0 Mar 19 22:08 src/
422/466
JEP-483: Ahead-of-Time Class
Loading and Linking
 Example of Spring PetClinic (!)
– Version 3.2.0
– Loads and links ~21,000 classes
– Startup times
• Without AOT cache 4.486s (JDK 23)
• With AOT cache 2.604s (JDK 24, 42%)
423/466
JEP-491: Synchronize Virtual
Threads without Pinning
 Virtual threads
 Platform threads
 Arrange “for virtual threads that block in
[synchronized methods and blocks] to
release their underlying platform threads”
424/466
APIS
425/466
JEP-484: Class-File API
 Non-goals
– “[O]bsolete existing libraries [for] class files”
• Apache BCEL
• IBM CFParse
– “[E]xtend the Core Reflection API to give access
to the bytecode of loaded classes.”
• Would require changes to the JVM
– “[P]rovide code analysis functionality”
• Should be provided by third-party libraries
426/466
JEP-484: Class-File API
 Manipulate class-files directly in Java
ClassFile.of().buildTo(Path.of("A.class"), ClassDesc.of("A"),
classBuilder -> classBuilder.withMethod("fooBar",
MethodTypeDesc.of(CD_void, CD_boolean, CD_int),
AccessFlags.ofMethod(AccessFlag.PUBLIC).flagsMask(),
methodBuilder -> methodBuilder.withCode(codeBuilder -> {
final Label label1 = codeBuilder.newLabel();
final Label label2 = codeBuilder.newLabel();
codeBuilder.iload(1).ifeq(label1).aload(0).iload(2)
.invokevirtual(ClassDesc.of("Foo"), "foo",
MethodTypeDesc.of(CD_void, CD_int))
.goto_(label2).labelBinding(label1).aload(0)
.iload(2)
.invokevirtual(ClassDesc.of("Foo"), "bar",
MethodTypeDesc.of(CD_void, CD_int))
.labelBinding(label2).return_();
})));
427/466
JEP-485: Stream Gatherers
 Map-Reduce
– Processing, generating
large data sets
– Parallel and distributed
 Streaming platforms
– Unified, high-throughput,
low-latency
– Apache Kafka
 Sequence of data
– Declarative, functional
– Parallel and distributed
https://www.oracle.com/technical-resources/articles/java/ma14-java-se-8-streams.html
428/466
JEP-485: Stream Gatherers
https://www.oracle.com/technical-resources/articles/java/ma14-java-se-8-streams.html
429/466
JEP-485: Stream Gatherers
private static final record Transaction(Type type, int id, int value) {
enum Type { GROCERY, ENTERTAINMENT; }
public Type getType() { return this.type; }
public int getValue() { return this.value; }
public int getId() { return this.id; }
}
public static void main(final String[] args) {
final List<Transaction> transactions = List.of(
new Transaction(Transaction.Type.ENTERTAINMENT, 1, 100),
new Transaction(Transaction.Type.GROCERY, 3, 80),
new Transaction(Transaction.Type.GROCERY, 6, 120),
new Transaction(Transaction.Type.ENTERTAINMENT, 7, 40),
new Transaction(Transaction.Type.GROCERY, 10, 50));
final List<Integer> transactionsIds = transactions.parallelStream()
.filter(t -> t.getType() == Transaction.Type.GROCERY)
.sorted(Comparator.comparing(Transaction::getValue).reversed())
.map(Transaction::getId).collect(Collectors.toList());
System.out.println(transactionsIds);
}
430/466
JEP-485: Stream Gatherers
private static final record Transaction(Type type, int id, int value) {
enum Type { GROCERY, ENTERTAINMENT; }
public Type getType() { return this.type; }
public int getValue() { return this.value; }
public int getId() { return this.id; }
}
public static void main(final String[] args) {
final List<Transaction> transactions = List.of(
new Transaction(Transaction.Type.ENTERTAINMENT, 1, 100),
new Transaction(Transaction.Type.GROCERY, 3, 80),
new Transaction(Transaction.Type.GROCERY, 6, 120),
new Transaction(Transaction.Type.ENTERTAINMENT, 7, 40),
new Transaction(Transaction.Type.GROCERY, 10, 50));
final List<Integer> transactionsIds = transactions.parallelStream()
.filter(t -> t.getType() == Transaction.Type.GROCERY)
.sorted(Comparator.comparing(Transaction::getValue).reversed())
.map(Transaction::getId).collect(Collectors.toList());
System.out.println(transactionsIds);
}
[6, 3, 10]
431/466
JEP-485: Stream Gatherers
 Stateless vs. Stateful methods
– filter() and map()
– distinct() and sorted()
• limit() cuts short the processing
https://www.logicbig.com/tutorials/core-java-tutorial/java-util-stream/stream-cheat-sheet.html
432/466
JEP-485: Stream Gatherers
 In particular
– distinct() uses equals()
– E.g., String content

@Override
public void accept(T t) {
if (t == null) {
if (!seenNull) {
seenNull = true;
downstream.accept(lastSeen = null);
}
} else if (lastSeen == null || !t.equals(lastSeen)) {
downstream.accept(lastSeen = t);
}
}
433/466
JEP-485: Stream Gatherers
 In particular
– distinct() uses equals()
– E.g., String content

@Override
public void accept(T t) {
if (t == null) {
if (!seenNull) {
seenNull = true;
downstream.accept(lastSeen = null);
}
} else if (lastSeen == null || !t.equals(lastSeen)) {
downstream.accept(lastSeen = t);
}
}
Object::equals()
434/466
JEP-485: Stream Gatherers
 In particular
– distinct() uses equals()
– E.g., String content
 What if we want String length?
@Override
public void accept(T t) {
if (t == null) {
if (!seenNull) {
seenNull = true;
downstream.accept(lastSeen = null);
}
} else if (lastSeen == null || !t.equals(lastSeen)) {
downstream.accept(lastSeen = t);
}
}
Object::equals()
435/466
JEP-485: Stream Gatherers
 Before, only equals()
 Now, any method and stateful object
final List<String> result = Stream
.of("foo", "bar", "bar", "bar", "zorg")
.distinct()
.toList();
final DifferentLength differentLength = new DifferentLength();
final List<String> result = Stream
.of("foo", "bar", "bar", "bar", "zorg")
.gather(Gatherer.ofSequential(
Integrator.ofGreedy(differentLength)))
.toList();
436/466
JEP-485: Stream Gatherers
 Or all-in-one
final List<String> result = Stream
.of("foo", "bar", "bar", "bar", "zorg")
.gather(Gatherer.ofSequential(
DifferentLength::new,
Integrator.ofGreedy(DifferentLength::integrate),
DifferentLength::finish))
.toList();
437/466
JEP-485: Stream Gatherers
class DifferentLength {
private final Set<Integer> setOfLengths;
DifferentLength() {this.setOfLengths = new HashSet<>(); }
boolean integrate(
final String element,final Downstream<? super String> downstream) {
final int length = element.length();
if (!setOfLengths.contains(length)) {
setOfLengths.add(length);
return downstream.push(element);
}
return true;
}
void finish(final Downstream<? super String> downstream) { }
}
final List<String> result = Stream
.of("foo", "bar", "bar", "bar", "zorg")
.gather(Gatherer.<String, DifferentLength, String>ofSequential(
DifferentLength::new,
Integrator.<DifferentLength, String, String>ofGreedy(DifferentLength::integrate),
DifferentLength::finish))
.toList();
438/466
JEP-485: Stream Gatherers
class DifferentLength {
private final Set<Integer> setOfLengths;
DifferentLength() {this.setOfLengths = new HashSet<>(); }
boolean integrate(
final String element,final Downstream<? super String> downstream) {
final int length = element.length();
if (!setOfLengths.contains(length)) {
setOfLengths.add(length);
return downstream.push(element);
}
return true;
}
void finish(final Downstream<? super String> downstream) { }
}
final List<String> result = Stream
.of("foo", "bar", "bar", "bar", "zorg")
.gather(Gatherer.<String, DifferentLength, String>ofSequential(
DifferentLength::new,
Integrator.<DifferentLength, String, String>ofGreedy(DifferentLength::integrate),
DifferentLength::finish))
.toList();
Any desired state!
439/466
JEP-485: Stream Gatherers
class DifferentLength {
private final Set<Integer> setOfLengths;
DifferentLength() {this.setOfLengths = new HashSet<>(); }
boolean integrate(
final String element,final Downstream<? super String> downstream) {
final int length = element.length();
if (!setOfLengths.contains(length)) {
setOfLengths.add(length);
return downstream.push(element);
}
return true;
}
void finish(final Downstream<? super String> downstream) { }
}
final List<String> result = Stream
.of("foo", "bar", "bar", "bar", "zorg")
.gather(Gatherer.<String, DifferentLength, String>ofSequential(
DifferentLength::new,
Integrator.<DifferentLength, String, String>ofGreedy(DifferentLength::integrate),
DifferentLength::finish))
.toList();
Any desired state!
Not very clear…
440/466
JEP-485: Stream Gatherers
 The optional initialiser function provides an
object that maintains private state
 The integrator function integrates a new
element from the input stream
 The optional combiner function can evaluate
the gatherer in parallel for parallel streams
 The optional finisher function is called when
there are no more input elements
441/466
JEP-496: Quantum-Resistant
Module-Lattice-Based Key
Encapsulation Mechanism
JEP-497: Quantum-Resistant
Module-Lattice-Based Digital
Signature Algorithm
 Post-quantum cryptography
– Algorithms secured against a cryptanalytic
attack by a quantum computer
442/466
JEP-496 and JEP-497
https://www.wsj.com/articles/d-wave-claims-quantum-supremacy-beating-traditional-computers-155ca634
443/466
JEP-496 and JEP-497
 Six main approaches
1. Lattice-based cryptography
2. Multivariate cryptography
3. Hash-based cryptography
4. Code-based cryptography
5. Isogeny-based cryptography
6. Symmetric key quantum resistance
444/466
JEP-496 and JEP-497
 Six main approaches
1. Lattice-based cryptography
2. Multivariate cryptography
3. Hash-based cryptography
4. Code-based cryptography
5. Isogeny-based cryptography
6. Symmetric key quantum resistance
445/466
JEP-496 and JEP-497
final KeyPairGenerator kpgKEM = KeyPairGenerator.getInstance("ML-KEM");
kpgKEM.initialize(NamedParameterSpec.ML_KEM_512);
final KeyPair kpKEM = kpgKEM.generateKeyPair(); // an ML-KEM-512 key pair
System.out.println(kpKEM.getPrivate());
System.out.println(kpKEM.getPublic());
final KeyPairGenerator kpgDSA = KeyPairGenerator.getInstance("ML-DSA");
kpgDSA.initialize(NamedParameterSpec.ML_DSA_44);
final KeyPair kpDSA = kpgDSA.generateKeyPair(); // an ML-DSA-44 key pair
System.out.println(kpDSA.getPrivate());
System.out.println(kpDSA.getPublic());
446/466
JEP-498: Warn upon Use of Memory-
Access Methods in sun.misc.Unsafe
 Now in module jdk.unsupported
 79 out of 87 methods for accessing memory
– JVM’s garbage-collected heap
– Off-heap memory (out of the JVM’s control)
447/466
JEP-498: Warn upon Use of Memory-
Access Methods in sun.misc.Unsafe
 java.lang.invoke.VarHandle
– JDK 9 (JEP-193)
– Safely and efficiently access on-heap memory,
i.e., fields of objects, fields of classes…
 java.lang.foreign.MemorySegment
– JDK 22 (JEP-454)
– Safely and efficiently access off-heap memory,
c.f., Project Panama
448/466
JEP-498: Warn upon Use of Memory-
Access Methods in sun.misc.Unsafe
 JDK 24: Warning
 JDK 26+: Exception
 JDK 27+: Removal of methods that have
standard and safe alternatives
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::setMemory has been called by com.foo.bar.Server
(file:/tmp/foobarserver/thing.jar)
WARNING: Please consider reporting this to the maintainers of com.foo.bar.Server
WARNING: sun.misc.Unsafe::setMemory will be removed in a future release
449/466
MISC
450/466
JEP-472: Prepare to Restrict the Use
of JNI
 Want integrity by default
– “[A]ll JDK features that are capable of breaking
integrity must obtain explicit approval from the
application's developer.”
451/466
JEP-472: Prepare to Restrict the Use
of JNI
1. Long values as addresses in memory
2. Byte buffers starting at address 0
3. Modifying immutable objects (e.g., Strings)
4. Writing past the end of an array
5. Using functions disturbing the GC
452/466
JEP-472: Prepare to Restrict the Use
of JNI
1. Long values as addresses in memory
void Java_pkg_C_setPointerToThree__J(jlong ptr) {
*(int*)ptr = 3;
}
453/466
JEP-472: Prepare to Restrict the Use
of JNI
2. Byte buffers starting at address 0
return (*env)->NewDirectByteBuffer(env, 0, 10);
454/466
JEP-472: Prepare to Restrict the Use
of JNI
3. Modifying immutable objects
jclass clazz = (*env)->FindClass(env, "java/lang/String");
jfieldID fid = (*env)->GetFieldID(env, clazz , "value", "[B");
jbyteArray contents = (jbyteArray)(*env)->GetObjectField(env, str, fid);
jbyte b = 0;
(*env)->SetByteArrayRegion(env, contents, 0, 1, &b);
455/466
JEP-472: Prepare to Restrict the Use
of JNI
4. Writing past the end of an array
jbyte *a = (*env)->GetPrimitiveArrayCritical(env, arr, 0);
a[500] = 3; // May be out of bounds
(*env)->ReleasePrimitiveArrayCritical(env, arr, a, 0);
456/466
JEP-472: Prepare to Restrict the Use
of JNI
5. Using functions disturbing the GC
“However, there are
significant restrictions on how
these functions can be used.”
https://shipilev.net/jvm/anatomy-quarks/9-jni-critical-gclocker/
457/466
JEP-472: Prepare to Restrict the Use
of JNI
 “Under the policy of integrity by default, it is
the application developer (or perhaps
deployer, on the advice of the application
developer) who enables native access”
458/466
JEP-472: Prepare to Restrict the Use
of JNI
 “Under the policy of integrity by default, it is
the application developer (or perhaps
deployer, on the advice of the application
developer) who enables native access”
WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::loadLibrary has been called by net.ptidej.newjava.restrictJNI.Main in module myModule (file:...)
WARNING: Use --enable-native-access=myModule to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
459/466
JEP-479: Remove the Windows
32-bit x86 Port
 “Allow contributors in the OpenJDK
Community to accelerate […] development”
 “JEP 436 (Virtual Threads) for Windows x86-
32 falls back [on] kernel threads [removing
the] benefits of Project Loom.”
 “Windows 10, the last Windows operating
system to support 32-bit operation, will reach
End of Life in October 2025.”
460/466
JEP-479: Remove the Windows
32-bit x86 Port
 Also related to JEP-501: Deprecate the 32-
bit x86 Port for Removal
– Linux 32-bit x86 port
461/466
JEP-486: Permanently Disable the
Security Manager
 “[T]he permission scheme is so complex that
the Security Manager has always been
disabled by default, and its use is […] rare.”
 “From networking, I/O, and JDBC, to XML,
AWT, and Swing, the libraries must
implement the least-privilege model in case
the Security Manager is enabled”
Emphasis mine
462/466
JEP-486: Permanently Disable the
Security Manager
 “[T]he permission scheme is so complex that
the Security Manager has always been
disabled by default, and its use is […] rare.”
 “From networking, I/O, and JDBC, to XML,
AWT, and Swing, the libraries must
implement the least-privilege model in case
the Security Manager is enabled”
Emphasis mine
463/466
JEP-486: Permanently Disable the
Security Manager
 “Over 1,000 methods must check for
permission”
 “Over 1,200 methods must elevate their
privileges”
 If needed, can be replaced outside of JVM
– An agent can block code from calling
System::exit
464/466
JEP-493: Linking Run-Time Images
without JMODs
 “Reduce the size of the JDK by […] 25% by
enabling the jlink tool to create custom
run-time images without using the JDK's
JMOD files.”
– JMOD is JAR with native code, configuration
files, and other kinds of data
465/466
466/466
Image Credits
 Disclaimer: https://www.elitelux.club/understanding-java-programming/
 Organisation: https://www.comsoftit.com/web.html
 Java 5&6: https://www.amazon.ca/JAVA-SYNTHESE-COURS-EXERCICES-CORRIGES/dp/2744072192
 Java 7: https://www.gizchina.com/2022/07/31/java-7-se-reaches-a-dead-end-java-8-becomes-the-norm/
 Java 8: https://www.infoworld.com/article/3676578/oracle-unveils-performance-pack-for-java-8.html
 Java 9: https://fossbytes.com/java-9-is-coming-release-date-features/
 Java 10: https://codepumpkin.com/java-10-features/
 Java 11: https://www.amazon.ca/Mastering-Java-Second-Edward-Lavieri/dp/1789137616
 Java 12: https://loiane.com/2019/03/what-is-new-in-java-12-api-for-developers/
 https://www.neosoft.fr/nos-publications/blog-tech/benchmark-java-introduction-a-jmh/
 Java 13: https://java-13.com/
 Java 14: https://dzone.com/refcardz/java-14-1
 Java 15: https://dev.to/aaiezza/are-you-seriously-not-using-java-15-yet-5c86
 Java 16: https://www.azul.com/blog/67-new-features-in-jdk-16/
 Java 17: https://www.codingknownsense.com/clear-your-concept/java-17-a-brief-overview-of-features-and-enhancements/
 Java 18: https://twitter.com/Sharat_Chander/status/1506279732094148627
 Java 19: https://medium.com/codex/java-19-the-new-features-1bb1b6bed83c
 https://wiki.openjdk.org/display/duke/Gallery
 https://guigarage.com/
 Java 20: https://dev.to/symflower/what-is-new-in-java-20-21gh
 Java 21: https://www.unlogged.io/post/all-you-need-to-know-about-java21
 Java 22: https://www.makb183.com/2023/10/java-22-what-to-expect.html
 Eager: https://www.facebook.com/eagertolearnJava/
 https://superacpov.live/product_details/50265612.html
 https://www.istockphoto.com/search/2/image?mediatype=illustration&phrase=warning+road+signs
 Java 23: https://www.heise.de/news/Java-23-erweitert-Import-und-Patterns-verzichtet-aber-auf-String-Templates-9870591.html
 Java 24: https://www.oracle.com/news/announcement/oracle-releases-java-24-2025-03-18/
 https://tenor.com/en-GB/view/the-simpsons-homer-bush-disappear-awkward-gif-4841810

Evolution and Examples of Java Features, from Java 1.7 to Java 24

  • 1.
    Yann-Gaël Guéhéneuc (/jan/, he/il) Worklicensed under Creative Commons BY-NC-SA 4.0 International New Java yann-gael.gueheneuc@concordia.ca Version 0.24 2025/03/18
  • 2.
    2/466 Any questions/comments arewelcome at yann-gael.gueheneuc@concordia.ca Source code available at https://github.com/ptidejteam/tutorials-NewJava
  • 3.
    3/466 Patrick Naughton Scott McNealy MikeSheridan James Gosling 1991
  • 4.
  • 5.
    5/466 Naming  Java – 1995/05/23 –Language  JDK (Java Development Kit) – Compiler (Java Language Specification) – VM (Java Virtual Machine Specification) – APIs/Libraries (Java Class Libraries)
  • 6.
    6/466 Process  JCP: JavaCommunity Process – Established in 1998 – JSR-387 describes JCP v2.11
  • 7.
    7/466 Documents  JLSs: JavaLanguage 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
  • 8.
  • 9.
    9/466 About the JDK Compiler – javac: compiler  Development – javadoc: documentation – jar: packaging – jdb: debugger  Management – jconsole: GUI – javaw: VM  Libraries – java.lang.…: mandatory classes – java.awt.…: graphical framework – javax.…: extensions https://medium.com/@zaam.oussama/java-development-kit-jdk-exploring-its-components-and-functionality-8f6d6c2a046c
  • 10.
  • 11.
  • 12.
    12/466 About the JDK Loading: JVM loads bytecode in .class files  Verification: JVM verifies the bytecode for Java’s safety and security rules  Execution: JVM interprets or compiles bytecode into native machine instructions  Optimization: JIT compiler optimises bytecode for faster execution https://medium.com/@zaam.oussama/java-development-kit-jdk-exploring-its-components-and-functionality-8f6d6c2a046c
  • 13.
    13/466 About the JDK Modularisation – Since Java 9 (2017)  Development – jlink: assembles and optimises a set of modules and their dependencies into a custom runtime image – jpackage: generates installable packages for (non-)modular programs – jmod: packages modules with native libraries or other configuration files (for jlink)  Runtime – A JDK image is a runtime image with development tools – A runtime image is a set of folders/files – URI scheme jrt:/ for naming stored modules, classes, and resources – No regression • Startup • Static footprint • Dynamic footprint
  • 14.
  • 15.
  • 16.
  • 17.
    17/466 Organisation  Per release –With some cross-references  Three categories – Language – JVM – APIs Misc +
  • 18.
    18/466 In Summary (With FewExamples)  Language – Reduce risk of bugs • try with resources – Simplify coding • switch with Strings, expressions, pattern matching – Improve typing • Diamond operator, annotations, inferences – Make the language more functional • λ-expressions (+ rewrite of many APIs) – Control finely accessibility/visibility • Modules, records, sealed classes, hidden classes
  • 19.
    19/466 In Summary (With FewExamples)  JVM – APIs • Tools • GCs – Release • Statically-linked libraries – Performance • JIT – Graal VM • GCs – Implementations – NUMA
  • 20.
    20/466 In Summary (With FewExamples)  APIs – Reduce risk of bugs • Concurrency • Date and Time – Simplify coding • New file I/O • HTTP client and server • Foreign Function and Memory API
  • 21.
    21/466 In Summary (With FewExamples)  Misc. – Coding • jshell • Java files launching • Instance main method – Release • jlink and jpackage – Performance • jaotc
  • 22.
  • 23.
  • 24.
    24/466 Enums  Special datatype – 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(); } }
  • 25.
    25/466 Enums  Based onanonymous 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); }
  • 26.
    26/466 Enums  Based onanonymous 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()
  • 27.
    27/466 Enums Enum Simulated Enum interfaceInterface1 { 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(); } }
  • 28.
    28/466 Enums Enum Simulated Enum interfaceInterface1 { 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
  • 29.
    29/466 Enums Enum Simulated Enum interfaceInterface1 { 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
  • 30.
    30/466 Enums  More thanjust 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 // ... }
  • 31.
    31/466 Enums  More thanjust 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
  • 32.
    32/466 Enums  No workaround 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;
  • 33.
  • 34.
  • 35.
    35/466 Strings in switch https://www.baeldung.com/java-switch publicString exampleOfSwitch(String animal) { String result; switch (animal) { case "DOG" : result = "domestic animal"; break; case "CAT" : result = "domestic animal"; break; case "TIGER" : result = "wild animal"; break; default : result = "unknown animal"; break; } return result; }
  • 36.
    36/466 try With Resources New interfaces – java.lang.Closeable – java.lang.AutoCloseable https://www.baeldung.com/java-try-with-resources try (final Scanner scanner = new Scanner(new File("test.txt"))) { while (scanner.hasNext()) { System.out.println(scanner.nextLine()); } } catch (final FileNotFoundException fnfe) { fnfe.printStackTrace(); }
  • 37.
    37/466 Diamond Operator <> https://www.baeldung.com/java-diamond-operator List<String>cars = new ArrayList<String>(); List<String> cars = new ArrayList<>(); vs.
  • 38.
    38/466 Vargs in MethodDeclaration https://www.baeldung.com/java-varargs https://www.baeldung.com/java-varargs public String format() { // ... } public String format(String value) { //... } public String format(String val1, String val2) { // ... } public String formatWithVarArgs(String... values) { System.out.println(values[0]); System.out.println(values[1]); System.out.println(values[3]); // ... } vs.
  • 39.
    39/466 Binary Integer Literals https://www.geeksforgeeks.org/java-program-to-illustrate-use-of-binary-literals/ //Byte type Binary Literal byte a1 = 0b011; // Short type Binary Literal short b1 = 0b101; // Int type Binary literal int c1 = 0b011; // Long type Binary literal long d1 = 0b0000011111100011;
  • 40.
    40/466 Underscores in NumericLiterals int i = 12_34_56; System.out.println(i); https://www.geeksforgeeks.org/using-underscore-numeric-literals-java/
  • 41.
    41/466 Multiple Exception Types Multiple exception types  Multiple exceptions rethrown with improved type checking
  • 42.
    42/466 Multiple Exception Types publicstatic void main(final String[] args) { try { Example1.rethrow("abc"); } catch (final FirstException | SecondException e) { // Below assignment would throw a compile-time exception, e is implicitly final // e = new Exception(); System.out.println(e.getMessage()); } } private static void rethrow(final String s) throws FirstException, SecondException { try { if (s.equals("First")) throw new FirstException("First"); else throw new SecondException("Second"); } catch (final Exception e) { // Below assignment would disable improved rethrow exception type checking // e = new ThirdException(); throw e; } } private static class FirstException extends Exception { public FirstException(String msg) { super(msg); } } // ...
  • 43.
  • 44.
    44/466 JSR-292: invokedynamic  invokestatic,for class methods  invokevirtual, for instance methods  invokeinterface, for interface methods  invokespecial, for instance initialisation, superclass, and private methods
  • 45.
  • 46.
    46/466 JSR-292: invokedynamic  invokedynamicindicates that a dynamic language run-time specific call occurs  The call occurs through MethodHandle(s) https://www.baeldung.com/java-method-handles MethodHandles.Lookup publicLookup = MethodHandles.publicLookup(); MethodType mt = MethodType.methodType(String.class, char.class, char.class); MethodHandle replaceMH = publicLookup.findVirtual(String.class, "replace", mt); String output = (String) replaceMH.invoke("jovo", 'o', 'a');
  • 47.
  • 48.
    48/466 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
  • 49.
  • 50.
  • 51.
  • 52.
    52/466 JSR-166: Concurrency Utilities https://gee.cs.oswego.edu/dl/concurrency-interest/jsr166-slides.pdf finalRunnable runnable1 = new RunnableExample("executor.execute(...)"); final ExecutorService executor = Executors.newFixedThreadPool(10); executor.execute(runnable1); final Runnable runnable2 = new RunnableExample("new Thread(...)"); new Thread(runnable2).start(); vs.
  • 53.
    53/466 JSR-166: Concurrency Utilities classImageRenderer { Image render(final byte[] raw) { return // ... } } public class Example2 { public void display(final byte[] raw) throws InterruptedException, ExecutionException { final ExecutorService executor = Executors.newFixedThreadPool(10); final ImageRenderer renderer = new ImageRenderer(); final Future<Image> image = executor.submit(new Callable<Image>() { public Image call() { return renderer.render(raw); } }); drawBorders(); // do other things ... drawCaption(); // ... while executing drawImage(image.get()); // use Future } // ... https://gee.cs.oswego.edu/dl/concurrency-interest/jsr166-slides.pdf
  • 54.
    54/466 JSR-166: Concurrency Utilities publicvoid run() { synchronized (this.resource) { this.resource.doSomething(); } this.resource.doLogging(); } public void run() { try { if (this. lock.tryLock(10, TimeUnit.SECONDS)) { this.resource.doSomething(); } } catch (final InterruptedException exception) { exception.printStackTrace(); } finally { this.lock.unlock(); } this.resource.doLogging(); } vs. https://www.digitalocean.com/com munity/tutorials/java-lock-example- reentrantlock
  • 55.
    55/466 JSR-166: Concurrency Utilities https://www.geeksforgeeks.org/semaphore-in-java/ privatefinal Semaphore semaphore; private void connect(final String user) throws InterruptedException { System.out.println(getCurrentDateTime() + " : " + user + " waiting sem"); this.semaphore.acquire(); System.out.println(getCurrentDateTime() + " : " + user + " acquired sem"); Thread.sleep(1000); // Some work... this.semaphore.release(); System.out.println(getCurrentDateTime() + " : " + user + " released sem"); } https://mkyong.com/java/java-semaphore-examples/
  • 56.
    56/466 JSR-166: Concurrency Utilities https://www.geeksforgeeks.org/atomic-variables-in-java-with-examples/ classCounter extends Thread { private final AtomicInteger count; public Counter() { this.count = new AtomicInteger(); } public void run() { final int max = 10_000_000; for (int i = 0; i < max; i++) { count.addAndGet(1); } } public int getCount() { return this.count.get(); } }
  • 57.
    57/466 JSR-203: New FileI/O Library  Extensive File I/O API  Socket channel API  Asynchronous I/O API
  • 58.
    58/466 JSR-203: New FileI/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); } }
  • 59.
    59/466 JSR-203: New FileI/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; } }
  • 60.
    60/466 JSR-203: New FileI/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
  • 61.
    61/466 JSR-203: New FileI/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(); }
  • 62.
    62/466 JSR-203: New FileI/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
  • 63.
    63/466 JSR-203: New FileI/O Library  Asynchronous I/O API “The asynchronous channel APIs were introduced into the existing java.nio.channels package […] by prefixing […] with Asynchronous”
  • 64.
    64/466 Translucent and ShapedWindows  Improves Java Swing  Allow new, nicer themes https://ateraimemo.com/Swing/TranslucentFrame.html Window.setShape(Shape s) Window.setOpacity(float f)
  • 65.
    65/466 Network Protocols  Networkprotocols – 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(); // ...
  • 66.
    66/466 Updates to XMLand 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
  • 67.
  • 68.
  • 69.
    69/466 default, static InterfaceMethods 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()); }
  • 70.
    70/466 default, static InterfaceMethods 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
  • 71.
    71/466 default, static InterfaceMethods  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()); }
  • 72.
    72/466 default, static InterfaceMethods  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()); }
  • 73.
    73/466 default, static InterfaceMethods  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());
  • 74.
    74/466 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
  • 75.
    75/466 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!")); }
  • 76.
    76/466 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!")); }
  • 77.
    77/466 JSR-335, JEP-126: λExpressions  Solution – Simple syntactic sugar – Set of functional interfaces – Libraries using these interfaces
  • 78.
    78/466 JSR-335, JEP-126: λExpressions  Solution – Simple syntactic sugar – Set of functional interfaces – Libraries using these interfaces
  • 79.
    79/466 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!")); }
  • 80.
    80/466 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!")); }
  • 81.
    81/466 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
  • 82.
    82/466 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
  • 83.
    83/466 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
  • 84.
    84/466 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> namesStartingWithR = friends.stream(). filter(name -> name.startsWith("R")).collect(Collectors.toList()); System.out.println(namesStartingWithR);
  • 85.
    85/466 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.
  • 86.
    86/466 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.
  • 87.
    87/466 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.
  • 88.
    88/466 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.
  • 89.
    89/466 JSR-308, JEP-104: TypeAnnotations  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); } }
  • 90.
    90/466 JSR-308, JEP-104: TypeAnnotations  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); } }
  • 91.
    91/466 JSR-308, JEP-104: TypeAnnotations  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
  • 92.
    92/466 JSR-308, JEP-104: TypeAnnotations  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
  • 93.
    93/466 JSR-308, JEP-104: TypeAnnotations 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); } } }
  • 94.
    94/466 JSR-308, JEP-104: TypeAnnotations 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'
  • 95.
    95/466 JSR-308, JEP-104: TypeAnnotations  “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/
  • 96.
    96/466 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)"); } } }
  • 97.
    97/466 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/
  • 98.
    98/466 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/
  • 99.
    99/466 JEP-120: Repeating Annotations https://rolyhewage.medium.com/type-annotations-repeating-annotations-in-java-722073df9f99 @Retention(RetentionPolicy.RUNTIME) @interfaceScheduleNonRepeatable1 { String dayOfMonth() default "First"; String dayOfWeek() default "Mon"; int hour() default 12; } @ScheduleNonRepeatable1(dayOfWeek = "Fri", hour = 23) public class Example1 { public static void main(final String[] args) { final Example1 example1 = new Example1(); final Annotation annotation = example1.getClass(). getAnnotation(ScheduleNonRepeatable1.class); System.out.println(annotation); } }
  • 100.
    100/466 JEP-120: Repeating Annotations https://rolyhewage.medium.com/type-annotations-repeating-annotations-in-java-722073df9f99 @Retention(RetentionPolicy.RUNTIME) @interfaceScheduleNonRepeatable1 { String dayOfMonth() default "First"; String dayOfWeek() default "Mon"; int hour() default 12; } @ScheduleNonRepeatable1(dayOfWeek = "Fri", hour = 23) public class Example1 { public static void main(final String[] args) { final Example1 example1 = new Example1(); final Annotation annotation = example1.getClass(). getAnnotation(ScheduleNonRepeatable1.class); System.out.println(annotation); } } @ScheduleNonRepeatable1(hour=23, dayOfMonth="First", dayOfWeek="Fri")
  • 101.
    101/466 JEP-120: Repeating Annotations https://rolyhewage.medium.com/type-annotations-repeating-annotations-in-java-722073df9f99 @Retention(RetentionPolicy.RUNTIME) @interfaceScheduleNonRepeatable2 { String dayOfMonth() default "First"; String dayOfWeek() default "Mon"; int hour() default 12; } @ScheduleNonRepeatable2(dayOfMonth = "last") @ScheduleNonRepeatable2(dayOfWeek = "Fri", hour = 23) public class Example2 { public static void main(final String[] args) { final Example2 example2 = new Example2(); final Annotation annotation = example2.getClass(). getAnnotation(ScheduleNonRepeatable2.class); System.out.println(annotation); } }
  • 102.
    102/466 JEP-120: Repeating Annotations https://rolyhewage.medium.com/type-annotations-repeating-annotations-in-java-722073df9f99 @Retention(RetentionPolicy.RUNTIME) @interfaceScheduleNonRepeatable2 { String dayOfMonth() default "First"; String dayOfWeek() default "Mon"; int hour() default 12; } @ScheduleNonRepeatable2(dayOfMonth = "last") @ScheduleNonRepeatable2(dayOfWeek = "Fri", hour = 23) public class Example2 { public static void main(final String[] args) { final Example2 example2 = new Example2(); final Annotation annotation = example2.getClass(). getAnnotation(ScheduleNonRepeatable2.class); System.out.println(annotation); } } Duplicate annotation of non-repeatable type @ScheduleNonRepeatable2
  • 103.
    103/466 JEP-120: Repeating Annotations https://rolyhewage.medium.com/type-annotations-repeating-annotations-in-java-722073df9f99 @Retention(RetentionPolicy.RUNTIME) @interfaceSchedules { ScheduleRepeatable[] value(); } @Retention(RetentionPolicy.RUNTIME) @Repeatable(Schedules.class) @interface ScheduleRepeatable { String dayOfMonth() default "First"; String dayOfWeek() default "Mon"; int hour() default 12; } @ScheduleRepeatable(dayOfMonth = "last") @ScheduleRepeatable(dayOfWeek = "Fri", hour = 23) public class Example3 { public static void main(final String[] args) { final Example3 example3 = new Example3(); final Annotation annotation = example3.getClass(). getAnnotation(Schedules.class); System.out.println(annotation); } }
  • 104.
    104/466 JEP-120: Repeating Annotations https://rolyhewage.medium.com/type-annotations-repeating-annotations-in-java-722073df9f99 @Retention(RetentionPolicy.RUNTIME) @interfaceSchedules { ScheduleRepeatable[] value(); } @Retention(RetentionPolicy.RUNTIME) @Repeatable(Schedules.class) @interface ScheduleRepeatable { String dayOfMonth() default "First"; String dayOfWeek() default "Mon"; int hour() default 12; } @ScheduleRepeatable(dayOfMonth = "last") @ScheduleRepeatable(dayOfWeek = "Fri", hour = 23) public class Example3 { public static void main(final String[] args) { final Example3 example3 = new Example3(); final Annotation annotation = example3.getClass(). getAnnotation(Schedules.class); System.out.println(annotation); } } @Schedules({@ScheduleRepeatable(hour=12, dayOfMonth="last", dayOfWeek="Mon"), @ScheduleRepeatable(hour=23, dayOfMonth="First", dayOfWeek="Fri")})
  • 105.
  • 106.
    106/466 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
  • 107.
    107/466 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
  • 108.
  • 109.
    109/466 JEP-174: Nashorn JSEngine  Successor of Mozilla’s Rhino  100% in ECMAScript v5.1 test suite  Java 8: Introduced  Java 11: Deprecated  Java 15: Removed
  • 110.
    110/466 JEP-174: Nashorn JSEngine  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);
  • 111.
    111/466 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.*
  • 112.
  • 113.
    113/466 JEP-153: JavaFX Applications Three “types” of programs – Class files – JAR files – JavaFX  Enhance the java command-line to launch JavaFX programs
  • 114.
  • 115.
  • 116.
    116/466 Private Interface Methods publicinterface 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()); }
  • 117.
    117/466 Private Interface Methods publicinterface 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
  • 118.
    118/466 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/
  • 119.
    119/466 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
  • 120.
    120/466 JSR-376: Modularization  Classpath/ JARs Hell  Version conflicts  Large Monolithic JDK  Security Problems https://www.geeksforgeeks.org/jpms-java-platform-module-system/
  • 121.
    121/466 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/
  • 122.
    122/466 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/
  • 123.
    123/466 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/
  • 124.
  • 125.
    125/466 JSR-376: Modularization  Amodule 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
  • 126.
    126/466 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; }
  • 127.
    127/466 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; }
  • 128.
    128/466 JSR-376: Modularization  Declarationof 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; }
  • 129.
    129/466 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; }
  • 130.
    130/466 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; }
  • 131.
    131/466 module com.example.foo { requirestransitive 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
  • 132.
    132/466 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
  • 133.
    133/466 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!)
  • 134.
    134/466 JSR-376: Modularization final Interfaceaki = 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
  • 135.
    135/466 JSR-376: Modularization  Theclient 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 ...
  • 136.
    136/466 JSR-376: Modularization  Theclient 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
  • 137.
    137/466 JSR-376: Modularization  Client Provider module ModularizationWithModulesClient1 { requires ModularizationWithModulesLibrary1; } module ModularizationWithModulesLibrary1 { exports net.ptidej.modularisation.kernel; exports net.ptidej.modularisation.kernel.impl; }
  • 138.
    138/466 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
  • 139.
    139/466 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
  • 140.
    140/466 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
  • 141.
    141/466 JSR-376: Modularization  Client Provider module ModularizationWithModulesClient2 { requires ModularizationWithModulesLibrary2; uses net.ptidej.modularisation.kernel.Interface; } module ModularizationWithModulesLibrary2 { exports net.ptidej.modularisation.kernel; provides net.ptidej.modularisation.kernel.Interface with net.ptidej.modularisation.kernel.impl.Implementation; }
  • 142.
    142/466 JSR-376: Modularization  Clientimplementation  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();
  • 143.
    143/466 JSR-376: Modularization  Clientimplementation  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();
  • 144.
    144/466 JSR-376: Modularization  Accessibility –Observability – Readability • requires vs. requires transitive – Visibility • public vs. “default” Problem: How to decide what packages and types are accessible? Solution: Readability vs. Visibility
  • 145.
    145/466 JSR-376: Modularization  Accessibility(bis) – Compile-time, run-time: --add-exports • Access to public types not exported via the module descriptor, for compilation and execution – Run-time only: --add-opens • Access to all types not exported via the module descriptor through reflection (cf. setAccessible())
  • 146.
    146/466 JSR-376: Modularization https://www.baeldung.com/java-illegal-reflective-access  Backwardcompatibility  Automatic module name – Classpath vs. Module path – JAR found on the module path
  • 147.
  • 148.
  • 149.
  • 150.
    150/466 JSR-376: Modularization  Relationto 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
  • 151.
    151/466 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
  • 152.
    152/466 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
  • 153.
    153/466 JEP-213: Milling ProjectCoin  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
  • 154.
  • 155.
    155/466  Nothing tomention, so much work went into modularisation
  • 156.
  • 157.
    157/466 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"); } }
  • 158.
    158/466 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)
  • 159.
    159/466 JavaDB Removal  JavaDBwas a repackaging of Apache Derby – Relational database – Open-source – Entirely in Java – Embedded JDBC driver
  • 160.
    160/466 JEP-254: Compact Strings Problemand 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
  • 161.
    161/466 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
  • 162.
    162/466 JEP-266: More onConcurrency  “[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));
  • 163.
    163/466 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>
  • 164.
  • 165.
  • 166.
    166/466 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
  • 167.
    167/466 JEP-295: jaotc  Ahead-of-timecompilation – 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
  • 168.
  • 169.
  • 170.
    170/466 JEP-286: Local-variable Type Inference finalList<String> list1 = new ArrayList<>(); System.out.println(list1); final var list2 = new ArrayList<String>(); System.out.println(list2); vs.
  • 171.
  • 172.
    172/466 JEP-304: GC Interface “Improve the source code isolation of different garbage collectors by introducing a clean garbage collector (GC) interface.” https://medium.com/@unmeshvjoshi/writing-your-own-garbage-collector-for-jdk12-8c83e3d0309b https://github.com/openjdk/jdk/blob/master/src/hotspot/share/gc/shared/collectedHeap.hpp#L90 class CollectedHeap : public CHeapObj<mtGC> { virtual jint initialize() = 0; virtual HeapWord* allocate_new_tlab(size_t min_size, size_t requested_size, size_t* actual_size) = 0; virtual HeapWord* mem_allocate(size_t size, bool* gc_overhead_limit_was_exceeded) = 0; // ...
  • 173.
    173/466 JEP-307: Parallel FullGC  Improve G1 worst-case with full parallel GC – Before Java 9: Parallel GC – Since Java 9: G1 https://dev.java/evolution/
  • 174.
    174/466 JEP-310: Application Class-Data Sharing Improve startup and footprint https://www.geeksforgeeks.org/class-data-sharing-in-java/ java -XX:+UnlockCommercialFeatures-XX:+UseAppCDS -XX:DumpLoadedClassList=LoadedClasses.1st -jar AppCDS.jar java -XX:+UnlockCommercialFeatures -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=LoadedClasses.1st -XX:SharedArchiveFile=CustomSharedArchive.jsa -cp AppCDS.jar java -XX:UnlockCommercialFeatures -verbose -XShare:on -XX:+UseAppCDS -XX:SharedArchiveFile=CUstomSharedArchive.jsa -jar AppCDS.jar
  • 175.
    175/466 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>
  • 176.
    176/466 JEP-316: Heap Allocationon 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>
  • 177.
    177/466 JEP-317: Experimental Java-based JITCompiler  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
  • 178.
  • 179.
    179/466 JEP-314: Additional Unicode Language-TagExtensions  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
  • 180.
  • 181.
    181/466 JEP-296: Consolidated JDKForest  Until Java 9 – Eight repos: root, corba, hotspot, jaxp, jaxws, jdk, langtools, and nashorn  Since Java 10 – One unified repository $ROOT/jdk/src/java.base ... $ROOT/langtools/src/java.compiler ...
  • 182.
    182/466 JEP-296: Consolidated JDKForest  Until Java 9 – Eight repos: root, corba, hotspot, jaxp, jaxws, jdk, langtools, and nashorn  Since Java 10 – One unified repository $ROOT/jdk/src/java.base ... $ROOT/langtools/src/java.compiler ... $ROOT/src/java.base $ROOT/src/java.compiler ...
  • 183.
    183/466 JEP-313: Native-Header Generation ToolRemoval  javah features (and more) now in javac javac HelloWorld.java javah HelloWorld javac -h jni -d bin HelloWorld.java vs.
  • 184.
    184/466 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
  • 185.
    185/466 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());
  • 186.
    186/466 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()); 21.0.1+12-LTS-29 Feature: 21 Interim: 0 Update: 1 Patch: 0 Build: Optional[12] Optional: Optional[LTS-29] Pre: Optional.empty
  • 187.
  • 188.
  • 189.
    189/466 JEP-181: Nest-based AccessControl  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(); } }
  • 190.
    190/466 JEP-181: Nest-based AccessControl 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); } } }
  • 191.
    191/466 JEP-181: Nest-based AccessControl 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
  • 192.
    192/466 JEP-323: Local-variable Syntaxfor 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")); } }
  • 193.
    193/466 JEP-323: Local-variable Syntaxfor 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
  • 194.
  • 195.
    195/466 JEP-309: Dynamic .classConstants  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
  • 196.
    196/466 JEP-309: Dynamic .classConstants 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"); } }
  • 197.
    197/466 JEP-309: Dynamic .classConstants 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; } }
  • 198.
    198/466 JEP-309: Dynamic .classConstants 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.
  • 199.
    199/466 JEP-309: Dynamic .classConstants 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
  • 200.
    200/466 JEP-309: Dynamic .classConstants  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
  • 201.
    201/466 JEP-309: Dynamic .classConstants  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
  • 202.
    202/466 JEP-309: Dynamic .classConstants 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());
  • 203.
    203/466 JEP-309: Dynamic .classConstants 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
  • 204.
    204/466 JEP-309: Dynamic .classConstants 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
  • 205.
    205/466 JEP-309: Dynamic .classConstants 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()
  • 206.
    206/466 JEP-309: Dynamic .classConstants 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
  • 207.
    207/466 JEP-309: Dynamic .classConstants 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
  • 208.
    208/466 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
  • 209.
  • 210.
    210/466 JEP-333: Scalable Low-latencyGC  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
  • 211.
  • 212.
    212/466 JEP-320: Java EEand 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
  • 213.
    213/466 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
  • 214.
    214/466 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
  • 215.
    215/466 JEP-321: https://www.baeldung.com/java-9-http-client final HttpRequest request= HttpRequest.newBuilder() .uri(new URI("https://postman-echo.com/get")) .version(HttpClient.Version.HTTP_2) .timeout(Duration.ofSeconds(10)) .header("key1", "value1") .header("key2", "value2") .GET() .build(); final HttpClient client = HttpClient.newHttpClient(); final HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
  • 216.
    216/466 JEP-321: https://www.baeldung.com/java-9-http-client final HttpRequest request= HttpRequest.newBuilder() .uri(new URI("https://postman-echo.com/get")) .version(HttpClient.Version.HTTP_2) .timeout(Duration.ofSeconds(10)) .header("key1", "value1") .header("key2", "value2") .GET() .build(); final HttpClient client = HttpClient.newHttpClient(); final HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); { "args": {}, "headers": { "x-forwarded-proto": "https", "x-forwarded-port": "443", "host": "postman-echo.com", "x-amzn-trace-id": "Root=1-660163f4-038cfd7075f93fad1e79f19e", "key1": "value1", "key2": "value2", "user-agent": "Java-http-client/21.0.1" }, "url": "https://postman-echo.com/get" }
  • 217.
    217/466 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
  • 218.
    218/466 JEP-335: Nashorn Deprecation Since Java 8 – JEP-174  ECMAScript changes rapidly – Language – APIs  Maintenance challenges – Deprecate Nashorn, its APIs, and jjs
  • 219.
  • 220.
    220/466 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
  • 221.
  • 222.
    222/466 JEP-330: Single-file Source-code ProgramsLaunching  Lower the (early) learning curve – But no dependency management java –cp some.jar HelloWorld.java
  • 223.
    223/466 JEP-336: Pack200 Toolsand 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
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
    228/466 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>
  • 229.
    229/466 JEP-346: Unused Committed MemoryPrompt 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>
  • 230.
  • 231.
    231/466 JEP-334: JVM ConstantsAPI  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); } }
  • 232.
    232/466 JEP-334: JVM ConstantsAPI  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]
  • 233.
  • 234.
    234/466 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
  • 235.
    235/466 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
  • 236.
    236/466 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
  • 237.
    237/466 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
  • 238.
    238/466 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
  • 239.
  • 240.
  • 241.
  • 242.
  • 243.
    243/466 JEP-351: Unused Memory Uncommit ZGC automatically returns heap memory to the operating system when idle – Cf. JEP-346 -XX:ZUncommitDelay=<seconds>
  • 244.
  • 245.
    245/466 JEP-353: Legacy SocketAPI Reimplementation  Reimplementations – java.net.Socket – java.net.ServerSocket  Simpler, modern  Easier to maintain, debug  Ready for user-mode threads – Fibers, Project Loom
  • 246.
  • 247.
  • 248.
  • 249.
  • 250.
    250/466 -XX:+ShowCodeDetailsInExceptionMessages JEP-358: Helpful NullPointerExceptions  Describeprecisely 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(); } }
  • 251.
    251/466 -XX:+ShowCodeDetailsInExceptionMessages JEP-358: Helpful NullPointerExceptions  Describeprecisely 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)
  • 252.
    252/466 -XX:+ShowCodeDetailsInExceptionMessages JEP-358: Helpful NullPointerExceptions  Describeprecisely 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)
  • 253.
    253/466 JEP-361: switch Expressions https://medium.com/@imagarg/switch-expression-jep-361-3b5649ec36c9 privatestatic 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; }
  • 254.
  • 255.
    255/466 JEP-345: NUMA-Aware Memory Allocation NUMA-aware memory allocation to increase G1 performance – Non-uniform memory access – Multi-socket computers • E.g., HP Z820 -XX:UseParallelGC=<true|false>
  • 256.
    256/466 JEP-345: NUMA-Aware Memory Allocation NUMA-aware memory allocation to increase G1 performance – Non-uniform memory access – Multi-socket computers • E.g., HP Z820 -XX:UseParallelGC=<true|false> Two CPUs, with their own DIMMs
  • 257.
    257/466 JEP-363: Concurrent MarkSweep GC Removal  Since Java 9 – Deprecated CMS  Reduce maintenance costs – Replaced by G1 – Two new GCs • ZGC • Shenandoah
  • 258.
  • 259.
    259/466 JEP-352: Non-volatile MappedByte Buffers  FileChannel can create MappedByteBuffer that access non-volatile memory – Cf. JEP-316 https://mashona.io/blog/2020/03/17/using-jep-352-api final File file = new File("/path/to/some/file"); final FileChannel fileChannel = (FileChannel) Files.newByteChannel(file.toPath(), EnumSet.of(StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE)); try { final MappedByteBuffer mappedByteBuffer = fileChannel.map(MapMode.READ_WRITE, position, size); // ... } catch (final IOException e) { // ... }
  • 260.
  • 261.
    261/466 JEP-349: JFR EventStreaming  API for the streaming of JFR data – In-process, out-of-process programs – Cf. JEP-328  Example: Health Report https://blogs.oracle.com/javamagazine/post/java-flight-recorder-and-jfr-event-streaming-in-java-14 https://github.com/flight-recorder/health-report java -javaagent:health-report.jar com.example.MyProgram
  • 262.
    262/466 JEP-349: JFR EventStreaming  Example: Health Report https://blogs.oracle.com/javamagazine/post/java-flight-recorder-and-jfr-event-streaming-in-java-14 https://github.com/flight-recorder/health-report =================== HEALTH REPORT === 2021-05-13 23:57:50 ==================== | GC: G1Old/G1New Phys. memory: 28669 MB Alloc Rate: 8 MB/s | | OC Count : 28 Initial Heap: 448 MB Total Alloc: 190 MB | | OC Pause Avg: 40.1 ms Used Heap : 19 MB Thread Count: 20.0 | | OC Pause Max: 48.8 ms Commit. Heap: 47 MB Class Count : 3894.0 | | YC Count : 8 CPU Machine : 20.12 % Safepoints: 335 | | YC Pause Avg: 5.7 ms CPU JVM User : 10.28 % Max Safepoint: 46.4 ms | | YC Pause Max: 22.4 ms CPU JVM System: 1.07 % Max Comp. Time: 728.3 ms | |--- Top Allocation Methods ------------------------------- -----------------| | DataBufferInt.(int) 11.27 % | | Component.size() 9.01 % | | BufferedContext.validate(...) 6.21 % | | Path2D$Double.(...) 5.87 % | | SunGraphics2D.clone() 5.85 % | |--- Hot Methods ------------------------------------------------------------| | DRenderer._endRendering(int, int) 51.11 % | | DRenderer.copyAARow(...) 6.67 % | | Arrays.fill(...) 4.44 % | | StringConcatFactory.doStringConcat(...) 2.22 % | | MarlinTileGenerator.getAlphaNoRLE(...) 2.22 % | ==============================================================================
  • 263.
  • 264.
  • 265.
    265/466 JEP-371: Hidden Classes Classes – Member classes  Methods – Inner classes – Anonymous classes – Lambda expressions  Encapsulation  Reflection
  • 266.
    266/466 JEP-371: Hidden Classes Hidden classes – Dynamic class creation (and their instances) – Classes that are not publicly visible/accessible  Improve – Encapsulation • Internal implementations – Security • Risk of unauthorized access (or tampering) https://www.javacodegeeks.com/2024/02/explore-java-15s-hidden-classes-with-code-examples.html
  • 267.
    267/466 JEP-371: Hidden Classes classTopLevelClass { public class MemberClass { } } public class Example1 { public static void main(final String[] args) throws ClassNotFoundException { class InnerClass { } final InnerClass innerClass = new InnerClass(); final Callable<String> anonynmousClass = new Callable<String>() { @Override public String call() throws Exception { return null; }}; final Callable<String> lambdaExpression = () -> null; final Class<?> classOfClazz = Class.forName("[...].TopLevelClass"); InfoPrinter.printInfo(classOfClazz); final Class<?> classOfMemberClass = Class.forName("[...].TopLevelClass$MemberClass"); InfoPrinter.printInfo(classOfMemberClass); final Class<?> classOfInnerClass = innerClass.getClass(); // final Class<?> classOfInnerClass = Class.forName("[...].Example1$1InnerClass"); InfoPrinter.printInfo(classOfInnerClass); final Class<?> classOfAnonymousClass = anonynmousClass.getClass(); // final Class<?> classOfAnonymousClass = Class.forName("[...].Example1$1"); InfoPrinter.printInfo(classOfAnonymousClass); final Class<?> classOfLambdaExpression = lambdaExpression.getClass(); // final Class<?> classOfLambdaExpression = Class.forName("[...].Example1$$Lambda/???"); InfoPrinter.printInfo(classOfLambdaExpression); } }
  • 268.
    268/466 JEP-371: Hidden Classes classTopLevelClass { public class MemberClass { } } public class Example1 { public static void main(final String[] args) throws ClassNotFoundException { class InnerClass { } final InnerClass innerClass = new InnerClass(); final Callable<String> anonynmousClass = new Callable<String>() { @Override public String call() throws Exception { return null; }}; final Callable<String> lambdaExpression = () -> null; final Class<?> classOfClazz = Class.forName("[...].TopLevelClass"); InfoPrinter.printInfo(classOfClazz); final Class<?> classOfMemberClass = Class.forName("[...].TopLevelClass$MemberClass"); InfoPrinter.printInfo(classOfMemberClass); final Class<?> classOfInnerClass = innerClass.getClass(); // final Class<?> classOfInnerClass = Class.forName("[...].Example1$1InnerClass"); InfoPrinter.printInfo(classOfInnerClass); final Class<?> classOfAnonymousClass = anonynmousClass.getClass(); // final Class<?> classOfAnonymousClass = Class.forName("[...].Example1$1"); InfoPrinter.printInfo(classOfAnonymousClass); final Class<?> classOfLambdaExpression = lambdaExpression.getClass(); // final Class<?> classOfLambdaExpression = Class.forName("[...].Example1$$Lambda/???"); InfoPrinter.printInfo(classOfLambdaExpression); } } class net.ptidej.newjava.hiddenclasses.TopLevelClass Canonical name: net.ptidej.newjava.hiddenclasses.TopLevelClass Name: net.ptidej.newjava.hiddenclasses.TopLevelClass isHidden? false class net.ptidej.newjava.hiddenclasses.TopLevelClass$MemberClass Canonical name: net.ptidej.newjava.hiddenclasses.TopLevelClass.MemberClass Name: net.ptidej.newjava.hiddenclasses.TopLevelClass$MemberClass isHidden? false class net.ptidej.newjava.hiddenclasses.Example1$1InnerClass Canonical name: null Name: net.ptidej.newjava.hiddenclasses.Example1$1InnerClass isHidden? false class net.ptidej.newjava.hiddenclasses.Example1$1 Canonical name: null Name: net.ptidej.newjava.hiddenclasses.Example1$1 isHidden? false class net.ptidej.newjava.hiddenclasses.Example1$$Lambda/0x0000020a81000400 Canonical name: null Name: net.ptidej.newjava.hiddenclasses.Example1$$Lambda/0x0000020a81000400 isHidden? true
  • 269.
    269/466 JEP-371: Hidden Classes classTopLevelClass { public class MemberClass { } } public class Example1 { public static void main(final String[] args) throws ClassNotFoundException { class InnerClass { } final InnerClass innerClass = new InnerClass(); final Callable<String> anonynmousClass = new Callable<String>() { @Override public String call() throws Exception { return null; }}; final Callable<String> lambdaExpression = () -> null; final Class<?> classOfClazz = Class.forName("[...].TopLevelClass"); InfoPrinter.printInfo(classOfClazz); final Class<?> classOfMemberClass = Class.forName("[...].TopLevelClass$MemberClass"); InfoPrinter.printInfo(classOfMemberClass); final Class<?> classOfInnerClass = innerClass.getClass(); // final Class<?> classOfInnerClass = Class.forName("[...].Example1$1InnerClass"); InfoPrinter.printInfo(classOfInnerClass); final Class<?> classOfAnonymousClass = anonynmousClass.getClass(); // final Class<?> classOfAnonymousClass = Class.forName("[...].Example1$1"); InfoPrinter.printInfo(classOfAnonymousClass); final Class<?> classOfLambdaExpression = lambdaExpression.getClass(); // final Class<?> classOfLambdaExpression = Class.forName("[...].Example1$$Lambda/???"); InfoPrinter.printInfo(classOfLambdaExpression); } } class net.ptidej.newjava.hiddenclasses.TopLevelClass Canonical name: net.ptidej.newjava.hiddenclasses.TopLevelClass Name: net.ptidej.newjava.hiddenclasses.TopLevelClass isHidden? false class net.ptidej.newjava.hiddenclasses.TopLevelClass$MemberClass Canonical name: net.ptidej.newjava.hiddenclasses.TopLevelClass.MemberClass Name: net.ptidej.newjava.hiddenclasses.TopLevelClass$MemberClass isHidden? false class net.ptidej.newjava.hiddenclasses.Example1$1InnerClass Canonical name: null Name: net.ptidej.newjava.hiddenclasses.Example1$1InnerClass isHidden? false class net.ptidej.newjava.hiddenclasses.Example1$1 Canonical name: null Name: net.ptidej.newjava.hiddenclasses.Example1$1 isHidden? false class net.ptidej.newjava.hiddenclasses.Example1$$Lambda/0x0000020a81000400 Canonical name: null Name: net.ptidej.newjava.hiddenclasses.Example1$$Lambda/0x0000020a81000400 isHidden? true Hidden class
  • 270.
    270/466 JEP-371: Hidden Classes Use and features of hidden classes final InputStream stream = new FileInputStream(new File("rsc/HiddenClass.class")); final byte[] bytes = IOUtils.toByteArray(stream); final MethodHandles.Lookup lookup = MethodHandles.lookup(); final Class<?> hiddenClassClass1 = lookup.defineHiddenClass(bytes, true, STRONG).lookupClass(); InfoPrinter.printInfo(hiddenClassClass1); final Class<?> notHiddenClassClass1 = lookup.defineClass(bytes); InfoPrinter.printInfo(notHiddenClassClass1); final Class<?> notHiddenClassClass2 = myClassLoader.loadClass("[...].HiddenClass", bytes); InfoPrinter.printInfo(notHiddenClassClass2); final Class<?> hiddenClassClass2 = Class.forName(hiddenClassClass1.getName()); InfoPrinter.printInfo(hiddenClassClass2); final Class<?> hiddenClassClass3 = lookup.findClass(hiddenClassClass1.getName()); InfoPrinter.printInfo(hiddenClassClass3);
  • 271.
    271/466 JEP-371: Hidden Classes Use and features of hidden classes final InputStream stream = new FileInputStream(new File("rsc/HiddenClass.class")); final byte[] bytes = IOUtils.toByteArray(stream); final MethodHandles.Lookup lookup = MethodHandles.lookup(); final Class<?> hiddenClassClass1 = lookup.defineHiddenClass(bytes, true, STRONG).lookupClass(); InfoPrinter.printInfo(hiddenClassClass1); final Class<?> notHiddenClassClass1 = lookup.defineClass(bytes); InfoPrinter.printInfo(notHiddenClassClass1); final Class<?> notHiddenClassClass2 = myClassLoader.loadClass("[...].HiddenClass", bytes); InfoPrinter.printInfo(notHiddenClassClass2); final Class<?> hiddenClassClass2 = Class.forName(hiddenClassClass1.getName()); InfoPrinter.printInfo(hiddenClassClass2); final Class<?> hiddenClassClass3 = lookup.findClass(hiddenClassClass1.getName()); InfoPrinter.printInfo(hiddenClassClass3); class net.ptidej.newjava.hiddenclasses.HiddenClass/0x000001e2900082b0 Canonical name: null Name: net.ptidej.newjava.hiddenclasses.HiddenClass/0x000001e2900082b0 isHidden? true class net.ptidej.newjava.hiddenclasses.HiddenClass Canonical name: net.ptidej.newjava.hiddenclasses.HiddenClass Name: net.ptidej.newjava.hiddenclasses.HiddenClass isHidden? false class net.ptidej.newjava.hiddenclasses.HiddenClass Canonical name: net.ptidej.newjava.hiddenclasses.HiddenClass Name: net.ptidej.newjava.hiddenclasses.HiddenClass isHidden? false As expected, the hidden class cannot be discovered! As expected, the hidden class cannot be discovered!
  • 272.
    272/466 JEP-371: Hidden Classes Use and features of hidden classes final InputStream stream = new FileInputStream(new File("rsc/HiddenClass.class")); final byte[] bytes = IOUtils.toByteArray(stream); final MethodHandles.Lookup lookup = MethodHandles.lookup(); final Class<?> hiddenClassClass1 = lookup.defineHiddenClass(bytes, true, STRONG).lookupClass(); InfoPrinter.printInfo(hiddenClassClass1); final Class<?> notHiddenClassClass1 = lookup.defineClass(bytes); InfoPrinter.printInfo(notHiddenClassClass1); final Class<?> notHiddenClassClass2 = myClassLoader.loadClass("[...].HiddenClass", bytes); InfoPrinter.printInfo(notHiddenClassClass2); final Class<?> hiddenClassClass2 = Class.forName(hiddenClassClass1.getName()); InfoPrinter.printInfo(hiddenClassClass2); final Class<?> hiddenClassClass3 = lookup.findClass(hiddenClassClass1.getName()); InfoPrinter.printInfo(hiddenClassClass3); class net.ptidej.newjava.hiddenclasses.HiddenClass/0x000001e2900082b0 Canonical name: null Name: net.ptidej.newjava.hiddenclasses.HiddenClass/0x000001e2900082b0 isHidden? true class net.ptidej.newjava.hiddenclasses.HiddenClass Canonical name: net.ptidej.newjava.hiddenclasses.HiddenClass Name: net.ptidej.newjava.hiddenclasses.HiddenClass isHidden? false class net.ptidej.newjava.hiddenclasses.HiddenClass Canonical name: net.ptidej.newjava.hiddenclasses.HiddenClass Name: net.ptidej.newjava.hiddenclasses.HiddenClass isHidden? false As expected, the hidden class cannot be discovered! As expected, the hidden class cannot be discovered! Hidden classes are truly hidden
  • 273.
    273/466 JEP-378: Text Blocks Multi-line string literal – C++ • Compiler concatenates adjacent string literals • Escape embedded (invisible) newline chars – JavaScript • Template literals with ` (backtick) – Python • Use """
  • 274.
    274/466 JEP-378: Text Blocks Three quotes – Followed by white space(s) – Followed by a new line! final String textBlock = """ Hello World!"""; System.out.println(textBlock);
  • 275.
    275/466 JEP-378: Text Blocks Three quotes – Followed by white space(s) – Followed by a new line! final String textBlock = """ Hello World!"""; System.out.println(textBlock); Hello World!
  • 276.
  • 277.
    277/466 JEP-377: Scalable Low-latencyGC  Since Java 11 – Pause times not exceeding 10ms • With 2 MB or 2 TB heaps – Cf. JEP-333  ZGC becomes a product feature -XX:+UnlockExperimentalVMOptions -XX:+UseZGC
  • 278.
    278/466 JEP-379: Low-pause-time GC Since Java 12 – Consistent pause times • With 200 MB or 200 GB heaps – Cf. JEP-189  Shenandoah becomes a product feature XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC
  • 279.
  • 280.
    280/466 JEP-373: Legacy DatagramSocket APIReimplementation  Reimplementations – java.net.DatagramSocket – java.net.MulticastSocket  Since Java 1.0!  Concurrency issues  No clean support of IPv6  Mix of legacy Java and C code
  • 281.
    281/466 JEP-385: RMI ObjectActivation Deprecation  Since Java 1.1 – Remote Method Invocation  Since Java 1.2 – A remote object can be made persistent and later activated into a live object  Since Java 8 – Optional – Obsolete • Security
  • 282.
  • 283.
  • 284.
  • 285.
  • 286.
    286/466 JEP-390: Warnings forValue-based Classes  Value-based Classes – Marked with the final modifier – Equal solely based on equals() – Freely substitutable when equal – Instantiated via factory methods  With @ValueBased – Warning with identity-sensitive operations • Synchronisation, identity hashing, serialization… https://dzone.com/articles/moving-toward-inline-classes-jep-390-and-the-value
  • 287.
    287/466 JEP-394: Pattern Matchingfor instanceof  Testing if an expression is of a type and conditionally extracting components https://openjdk.org/jeps/394 final Object o1 = Integer.valueOf(1); if (o1 instanceof Integer) { final Integer integer = (Integer) o1; System.out.println(integer.intValue()); } public final boolean equals1(final Object o) { return (o instanceof String) && ((String) o).equalsIgnoreCase(string); }
  • 288.
    288/466 JEP-394: Pattern Matchingfor instanceof  Testing if an expression is of a type and conditionally extracting components https://openjdk.org/jeps/394 final Object o1 = Integer.valueOf(1); if (o1 instanceof Integer) { final Integer integer = (Integer) o1; System.out.println(integer.intValue()); } public final boolean equals1(final Object o) { return (o instanceof String) && ((String) o).equalsIgnoreCase(string); } final Object o3 = Integer.valueOf(3); if (o3 instanceof Integer integer) { System.out.println(integer.intValue()); } public final boolean equals2(final Object o) { return (o instanceof String s) && s.equalsIgnoreCase(string); }
  • 289.
    289/466 JEP-395: Records  Nominaltuples, with immutable data – private final – No setters https://www.baeldung.com/java-record-keyword record Person(String firstName, String lastName) { } // ... final Person person1 = new Person("Rick", "Deckard"); System.out.println(person1); final Person person2 = new Person("Rick", "Deckard"); System.out.println(person2); final Person person3 = new Person("Roy", "Batty"); System.out.println(person3); System.out.print(person1.firstName()); System.out.println(person1.equals(person2)); System.out.println(person1.equals(person3)); final Class<?> clazz = Class.forName("[...].Person"); final Field field = clazz.getDeclaredField("firstName"); field.set(person1, "Leon");
  • 290.
    290/466 JEP-395: Records  Nominaltuples, with immutable data – private final – No setters https://www.baeldung.com/java-record-keyword record Person(String firstName, String lastName) { } // ... final Person person1 = new Person("Rick", "Deckard"); System.out.println(person1); final Person person2 = new Person("Rick", "Deckard"); System.out.println(person2); final Person person3 = new Person("Roy", "Batty"); System.out.println(person3); System.out.print(person1.firstName()); System.out.println(person1.equals(person2)); System.out.println(person1.equals(person3)); final Class<?> clazz = Class.forName("[...].Person"); final Field field = clazz.getDeclaredField("firstName"); field.set(person1, "Leon"); IllegalAccessException
  • 291.
  • 292.
    292/466 JEP-347: C++14 LanguageFeatures  Use of C++14 in JDK C++ source code – Since Java 11 • C++ updated for recent C++ compilers – Until Java 15 • C++98/03  Specifics depend on the compiler /std:c++14 -std=c++14
  • 293.
    293/466 JEP-376: Concurrent Thread-stack Processing ZGC thread-stack processing – From safepoints to concurrent  Remove GC pauses and scalability issues  Make pauses sub-milliseconds
  • 294.
  • 295.
  • 296.
  • 297.
    297/466 JEP-392: Packaging Tool Since Java 14 – Native Java installer generator – Cf. JEP-343  From WORA to WORADA – Write Once, Run Anywhere – Write Once, Run Anywhere, Deploy Anywhere https://jfrog.com/blog/java-artifacts-just-got-better-jpackage-is-production-ready-in-java-16/
  • 298.
    298/466 JEP-392: Packaging Tool Without JRE  With (some of the) JRE – Cf. JSR-376 https://jfrog.com/blog/java-artifacts-just-got-better-jpackage-is-production-ready-in-java-16/ jpackage --name myprog --input lib --main-jar main.jar --main-class my.program.Main jlink --add-modules java.base,java.sql --output smalljre jpackage --name myprog --input lib --main-jar main.jar --main-class my.program.Main --runtime-image smalljre
  • 299.
  • 300.
  • 301.
    301/466 JEP-306: Always-strict Floating- pointSemantics Restoration  Consistently strict floating-point operations  Before – Platform-dependent floating-point representations, computations  Now – IEEE Standard for Floating Point Arithmetic • IEEE 754 – Warnings for unnecessary use of strictfp
  • 302.
    302/466 JEP-409: Sealed Classes Fine-grain control on subclassing – final – sealed • permits – non-sealed sealed class Person permits Employee, Student, Instructor { } final class Employee extends Person { } sealed class Student extends Person permits Bacc, Grad { } final class Bacc extends Student { } final class Grad extends Student { } non-sealed class Instructor extends Person { } class LTA extends Instructor { } class ETA extends Instructor { } class Prof extends Instructor { } // ... *https://www.reddit.com/r/java/comments/inol55/does_anyone_else_not_like_the_nonsealed_keyword/ but read also https://openjdk.org/jeps/8223002
  • 303.
    303/466 JEP-409: Sealed Classes Fine-grain control on subclassing – final – sealed • permits – non-sealed sealed class Person permits Employee, Student, Instructor { } final class Employee extends Person { } sealed class Student extends Person permits Bacc, Grad { } final class Bacc extends Student { } final class Grad extends Student { } non-sealed class Instructor extends Person { } class LTA extends Instructor { } class ETA extends Instructor { } class Prof extends Instructor { } // ... Ugly because negative and hyphenated* *https://www.reddit.com/r/java/comments/inol55/does_anyone_else_not_like_the_nonsealed_keyword/ but read also https://openjdk.org/jeps/8223002
  • 304.
  • 305.
  • 306.
  • 307.
    307/466 JEP-356: Enhanced Pseudo-random NumberGenerators https://www.baeldung.com/java-17-random-number-generators
  • 308.
    308/466 JEP-356: Enhanced Pseudo-random NumberGenerators  Beware of thread-safety! RandomGeneratorFactory.all().sorted( Comparator.comparing(RandomGeneratorFactory::name)) .forEach(factory -> System.out.println( String.format("%st%st%st%s", factory.group(), factory.name(), factory.isJumpable(), factory.isSplittable()))); final RandomGenerator generator = RandomGenerator.getDefault(); System.out.println(generator.nextInt());
  • 309.
    309/466 JEP-398: Applet APIDeprecation  No more support in Web browsers  Deprecated for removal – java.applet.Applet – java.applet.AppletStub – java.applet.AppletContext – java.applet.AudioClip – javax.swing.JApplet – java.beans.AppletInitializer
  • 310.
    310/466 JEP-415: Context-specific Deserialization Filters Context-specific, dynamically-selected deserialization filters -Djdk.serialFilter=net.ptidej.newjava.*;!* final ObjectInputFilter filter = ObjectInputFilter.Config.createFilter("net.ptidej.newjava.*;!*"); ObjectInputFilter.Config.setSerialFilter(filter); OR
  • 311.
  • 312.
  • 313.
  • 314.
  • 315.
    315/466 JEP-421: Finalization Deprecation  SinceJava 1.0 – finalize() method – E.g., in Caffeine (ASE’02)  Deprecation, disable, removal  Should be replaced with – try with resources • Cf. Java 7 – Cleaners
  • 316.
    316/466 JEP-421: Finalization Deprecation  SinceJava 9 – java.lang.ref.Cleaner – Cleanup actions for groups of objects https://howtodoinjava.com/java/basics/java-cleaners/ public static void main(final String[] args) throws Exception { try (final ResourceAccessingClass o = new ResourceAccessingClass()) { // Safely use the resource o.businessOperation1(); o.businessOperation2(); } }
  • 317.
    317/466 JEP-421: Finalization Deprecation  SinceJava 9 – java.lang.ref.Cleaner – Cleanup actions for groups of objects https://howtodoinjava.com/java/basics/java-cleaners/ public static void main(final String[] args) throws Exception { try (final ResourceAccessingClass o = new ResourceAccessingClass()) { // Safely use the resource o.businessOperation1(); o.businessOperation2(); } } Inside businessOperation1() with [...].Resource@65b54208 Inside businessOperation2() with [...].Resource@65b54208 Resource cleaned up
  • 318.
    318/466 JEP-421: Finalization Deprecation class Resource{ // Some (expensive) resource } class ResourceAccessingClass implements AutoCloseable { private final Cleaner cleaner = Example1.getCleaner(); private final Cleaner.Cleanable cleanable; private final Resource resource; public ResourceAccessingClass() { this.resource = new Resource(); this.cleanable = cleaner.register(this, () -> { System.out.println("Resource cleaned up");}); } public void businessOperation1() { System.out.print("Inside businessOperation1() with "); System.out.println(this.resource); } // ... https://howtodoinjava.com/java/basics/java-cleaners/
  • 319.
    319/466 JEP-421: Finalization Deprecation class Resource{ // Some (expensive) resource } class ResourceAccessingClass implements AutoCloseable { private final Cleaner cleaner = Example1.getCleaner(); private final Cleaner.Cleanable cleanable; private final Resource resource; public ResourceAccessingClass() { this.resource = new Resource(); this.cleanable = cleaner.register(this, () -> { System.out.println("Resource cleaned up");}); } public void businessOperation1() { System.out.print("Inside businessOperation1() with "); System.out.println(this.resource); } // ... https://howtodoinjava.com/java/basics/java-cleaners/ Register a Cleanable to clean asynchronously
  • 320.
  • 321.
  • 322.
  • 323.
    323/466 JEP-400: UTF-8 byDefault  UTF-8 by default  Consistent behaviour – Implementations – Operating systems – Locales  Except for console I/O https://en.wikipedia.org/wiki/UTF-8 Declared character set for the 10 million most popular websites, since 2010
  • 324.
    324/466 JEP-408: Simple WebServer  Command-line tool – Different from JEP-321  Minimal Web server – Static files only – No CGI or servlets https://www.baeldung.com/simple-web-server-java-18 jwebserver -d /opt Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::". Serving /opt and subdirectories on 127.0.0.1 port 8000 URL http://127.0.0.1:8000/
  • 325.
    325/466 JEP-408: Simple WebServer final InetSocketAddress address = new InetSocketAddress(8080); final Path path1 = Path.of("D:DocumentsTutorials220926 - New Java"); final HttpServer server = SimpleFileServer.createFileServer(address, path1, SimpleFileServer.OutputLevel.VERBOSE); final Path path2 = Path.of("D:DocumentsTutorials220926 - New JavaWorkspace"); final HttpHandler handler1 = SimpleFileServer.createFileHandler(path2); server.createContext("/test1", handler1); final HttpHandler allowedResponse = HttpHandlers.of(200, Headers.of("Allow", "GET"), "Welcome"); final HttpHandler deniedResponse = HttpHandlers.of(401, Headers.of("Deny", "GET"), "Denied"); final Predicate<Request> findAllowedPath = r -> r.getRequestURI().getPath().equals("/test2/allowed"); final HttpHandler handler2 = HttpHandlers.handleOrElse(findAllowedPath, allowedResponse, deniedResponse); server.createContext("/test2", handler2); server.start(); https://www.baeldung.com/simple-web-server-java-18
  • 326.
    326/466 JEP-416: Reflection with MethodHandles  Since Java 1.0 – sun.reflect.DelegatingMethodAccessorImpl – jdk.internal.reflect.DelegatingMethod AccessorImpl  Inflating implementation – First, native code – Then, dynamically-generated byte code • With some uses of sun.misc.Unsafe – Since Java 1.4 https://blogs.oracle.com/javamagazine/post/java-reflection-method-handles
  • 327.
    327/466 JEP-416: Reflection with MethodHandles  Method handles ≈ Reflection API https://blogs.oracle.com/javamagazine/post/java-reflection-method-handles int compare(final String str1, final String str2) { return 42; } int compare(final String str, final int i) { return 24; } public static void main(final String[] args) throws Throwable { var lookup = MethodHandles.lookup(); var methodType1 = MethodType.methodType(int.class, String.class, String.class); System.out.println("MethodType : " + methodType1); var methodHandle1 = lookup.findVirtual(lookup.lookupClass(), "compare", methodType1); System.out.println("MethodHandle: " + methodHandle1.type()); System.out.println(methodHandle1.invoke(new Example1(), "Hello", "World!")); var methodType2 = MethodType.methodType(int.class, String.class, int.class); var methodHandle2 = lookup.findVirtual(lookup.lookupClass(), "compare", methodType2); System.out.println(methodHandle2.invoke(new Example1(), "Hello", 0)); }
  • 328.
    328/466 JEP-416: Reflection with MethodHandles  Method handles ≈ Reflection API https://blogs.oracle.com/javamagazine/post/java-reflection-method-handles int compare(final String str1, final String str2) { return 42; } int compare(final String str, final int i) { return 24; } public static void main(final String[] args) throws Throwable { var lookup = MethodHandles.lookup(); var methodType1 = MethodType.methodType(int.class, String.class, String.class); System.out.println("MethodType : " + methodType1); var methodHandle1 = lookup.findVirtual(lookup.lookupClass(), "compare", methodType1); System.out.println("MethodHandle: " + methodHandle1.type()); System.out.println(methodHandle1.invoke(new Example1(), "Hello", "World!")); var methodType2 = MethodType.methodType(int.class, String.class, int.class); var methodHandle2 = lookup.findVirtual(lookup.lookupClass(), "compare", methodType2); System.out.println(methodHandle2.invoke(new Example1(), "Hello", 0)); } Introspection, really
  • 329.
    329/466 JEP-416: Reflection with MethodHandles  MethodHandles. lookup() – Methods, fields accessible where the lookup object is created – Inaccessible methods are not visible from the lookup context  MethodHandle. invoke() – Any arguments – Any return type – Varags (cf. Java 7) https://blogs.oracle.com/javamagazine/post/java-reflection-method-handles public final native @PolymorphicSignature Object invoke(Object...) throws Throwable;
  • 330.
    330/466 JEP-416: Reflection with MethodHandles  Method handles implement reflection – Without changing the Reflection API! • Since Java 1.1 – If old implementation is needed  Less overhead – MethodHandle.invokeWithArguments() callable by reflection and JNI https://blogs.oracle.com/javamagazine/post/java-reflection-method-handles Djdk.reflect.useDirectMethodHandle=false
  • 331.
    331/466 JEP-418: Internet-address Resolution SPI Service-provider interface (SPI) for host name and address resolution  Use (module) services – Cf. JSR-376  java.net.InetAddress can use resolvers – Others than the OS built-in resolver • hosts file and Domain Name System (DNS) public sealed class InetAddress implements Serializable permits Inet4Address, Inet6Address { private static InetAddressResolver loadResolver() { return ServiceLoader.load(InetAddressResolverProvider.class) .findFirst() .map(nsp -> nsp.get(builtinConfiguration())) .orElse(BUILTIN_RESOLVER); }
  • 332.
    332/466 JEP-418: Internet-address Resolution SPI Service-provider interface (SPI) for host name and address resolution  Use (module) services – Cf. JSR-376  java.net.InetAddress can use resolvers – Others than the OS built-in resolver • hosts file and Domain Name System (DNS) public sealed class InetAddress implements Serializable permits Inet4Address, Inet6Address { private static InetAddressResolver loadResolver() { return ServiceLoader.load(InetAddressResolverProvider.class) .findFirst() .map(nsp -> nsp.get(builtinConfiguration())) .orElse(BUILTIN_RESOLVER); } sealed class with two subclasses ServiceLoader with default object
  • 333.
  • 334.
  • 335.
  • 336.
  • 337.
  • 338.
  • 339.
  • 340.
  • 341.
    341/466 JEP-440: Record Patterns Since Java 16 – instanceof pattern matching – Records – Cf. JEP-394, JEP-395  Record patterns for record values
  • 342.
    342/466 JEP-440: Record Patterns recordPerson(String firstName, String lastName) { } public class Example1 { public static void main(final String[] args) { final Person person1 = new Person("Rick", "Deckard"); final Person person2 = new Person("Roy", "Batty"); final Object o1 = person1; if (o1 instanceof Person p) { System.out.println(p.firstName()); } final Object o2 = person2; if (o2 instanceof final Person(final String first, final String last)) { System.out.println(first); } } }
  • 343.
    343/466 JEP-440: Record Patterns recordPerson(String firstName, String lastName) { } public class Example1 { public static void main(final String[] args) { final Person person1 = new Person("Rick", "Deckard"); final Person person2 = new Person("Roy", "Batty"); final Object o1 = person1; if (o1 instanceof Person p) { System.out.println(p.firstName()); } final Object o2 = person2; if (o2 instanceof final Person(final String first, final String last)) { System.out.println(first); } } } Rick Roy
  • 344.
    344/466 JEP-441: switch PatternMatching final String response = "Yes"; switch (response) { case null -> { System.out.println("Boom!"); } case String s when s.equalsIgnoreCase("YES") -> { System.out.println("You got it"); } case String s when s.equalsIgnoreCase("NO") -> { System.out.println("Too bad"); } case String s -> { System.out.println("Sorry?"); } }
  • 345.
    345/466 JEP-441: switch PatternMatching final String response = "Yes"; switch (response) { case null -> { System.out.println("Boom!"); } case String s when s.equalsIgnoreCase("YES") -> { System.out.println("You got it"); } case String s when s.equalsIgnoreCase("NO") -> { System.out.println("Too bad"); } case String s -> { System.out.println("Sorry?"); } } You got it
  • 346.
  • 347.
    347/466 JEP-439: Generational ZGC Since Java 15 – Z Garbage Collector (ZGC) – Cf. JEP-377  Separate generations for young, old objects – More frequent collection of young objects – Minimal manual configuration -XX:+UseZGC -XX:+ZGenerational
  • 348.
  • 349.
    349/466 JEP-431: Sequenced Collections Inconsistencies in the collections – First, last elements – Reverse order https://www.baeldung.com/java-21-sequenced-collections Last Element First Element list.get(list.size() – 1) list.get(0) List deque.getLast() deque.getFirst() Deque sortedSet.last() sortedSet.first() SortedSet Missing linkedHS.iterator().next() LinkedHashSet
  • 350.
  • 351.
    351/466 JEP-431: Sequenced Collections https://www.baeldung.com/java-21-sequenced-collections publicinterface SequencedCollection<E> extends Collection<E> { SequencedCollection<E> reversed(); default void addFirst(E e) { throw new UnsupportedOperationException(); } default void addLast(E e) { throw new UnsupportedOperationException(); } default E getFirst() { return this.iterator().next(); } default E getLast() { return this.reversed().iterator().next(); } default E removeFirst() { var it = this.iterator(); E e = it.next(); it.remove(); return e; } default E removeLast() { var it = this.reversed().iterator(); E e = it.next(); it.remove(); return e; } } 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.getFirst()); System.out.println(list.getLast()); }
  • 352.
    352/466 JEP-431: Sequenced Collections https://www.baeldung.com/java-21-sequenced-collections publicinterface SequencedCollection<E> extends Collection<E> { SequencedCollection<E> reversed(); default void addFirst(E e) { throw new UnsupportedOperationException(); } default void addLast(E e) { throw new UnsupportedOperationException(); } default E getFirst() { return this.iterator().next(); } default E getLast() { return this.reversed().iterator().next(); } default E removeFirst() { var it = this.iterator(); E e = it.next(); it.remove(); return e; } default E removeLast() { var it = this.reversed().iterator(); E e = it.next(); it.remove(); return e; } } 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.getFirst()); System.out.println(list.getLast()); } Neat use of default methods (cf. Java 8)
  • 353.
    353/466 JEP-431: Sequenced Collections https://www.baeldung.com/java-21-sequenced-collections publicinterface SequencedCollection<E> extends Collection<E> { SequencedCollection<E> reversed(); default void addFirst(E e) { throw new UnsupportedOperationException(); } default void addLast(E e) { throw new UnsupportedOperationException(); } default E getFirst() { return this.iterator().next(); } default E getLast() { return this.reversed().iterator().next(); } default E removeFirst() { var it = this.iterator(); E e = it.next(); it.remove(); return e; } default E removeLast() { var it = this.reversed().iterator(); E e = it.next(); it.remove(); return e; } } 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.getFirst()); System.out.println(list.getLast()); } Rick Deckard Mary Neat use of default methods (cf. Java 8)
  • 354.
    354/466 JEP-444: Virtual Threads Since Java 1.0 – Thread-per-request style – Limited number of available threads  High-throughput concurrent programs  Virtual threads – Lightweight threads – Ease writing, maintaining, and observing
  • 355.
    355/466 JEP-444: Virtual Threads https://davidvlijmincx.com/posts/create_virtual_threads_with_project_loom/ finalRunnable printThread = () -> System.out.println(Thread.currentThread()); new Thread(printThread).start(); final ThreadFactory threadFactory1 = Thread.ofPlatform().factory(); final Thread platformThread2 = threadFactory1.newThread(printThread); platformThread2.start(); Thread.startVirtualThread(printThread); final ThreadFactory threadFactory2 = Thread.ofVirtual().factory(); final Thread virtualThread2 = threadFactory2.newThread(printThread); virtualThread2.start();
  • 356.
    356/466 JEP-444: Virtual Threads https://davidvlijmincx.com/posts/create_virtual_threads_with_project_loom/ finalRunnable printThread = () -> System.out.println(Thread.currentThread()); new Thread(printThread).start(); final ThreadFactory threadFactory1 = Thread.ofPlatform().factory(); final Thread platformThread2 = threadFactory1.newThread(printThread); platformThread2.start(); Thread.startVirtualThread(printThread); final ThreadFactory threadFactory2 = Thread.ofVirtual().factory(); final Thread virtualThread2 = threadFactory2.newThread(printThread); virtualThread2.start(); Thread[#20,Thread-0,5,main] Thread[#21,Thread-1,5,main] VirtualThread[#22]/runnable@ForkJoinPool-1-worker-1 VirtualThread[#24]/runnable@ForkJoinPool-1-worker-2
  • 357.
    357/466 JEP-452: Key Encapsulation MechanismAPI  Key encapsulation mechanisms (KEMs) – Securing symmetric keys – Using public key cryptography  Enable programs to use KEM algorithms  Allow implementations of KEM algorithms – Java code – Native code
  • 358.
  • 359.
    359/466 JEP-445: Unnamed Classesand Instance Main Methods  Reduce barrier to entry  Mimic scripting languages public class Example1 { public static void main(final String[] args) { System.out.println("Hello, World!"); } }
  • 360.
    360/466 JEP-445: Unnamed Classesand Instance Main Methods  Reduce barrier to entry  Mimic scripting languages public class Example1 { public static void main(final String[] args) { System.out.println("Hello, World!"); } } void main() { System.out.println("Hello, World!"); }
  • 361.
    361/466 JEP-445: Unnamed Classesand Instance Main Methods void main() { System.out.println("Hello, World!"); final Class clazz = this.getClass(); System.out.println(clazz.getName()); System.out.println(clazz.getPackage().getName()); System.out.println(clazz.getModule().getName()); } Example3.java
  • 362.
    362/466 JEP-445: Unnamed Classesand Instance Main Methods java --source 22 --enable-preview Example3.java void main() { System.out.println("Hello, World!"); final Class clazz = this.getClass(); System.out.println(clazz.getName()); System.out.println(clazz.getPackage().getName()); System.out.println(clazz.getModule().getName()); } Example3.java
  • 363.
    363/466 JEP-445: Unnamed Classesand Instance Main Methods java --source 22 --enable-preview Example3.java void main() { System.out.println("Hello, World!"); final Class clazz = this.getClass(); System.out.println(clazz.getName()); System.out.println(clazz.getPackage().getName()); System.out.println(clazz.getModule().getName()); } Hello, World! Example3 null Example3.java
  • 364.
    364/466 JEP-445: Unnamed Classesand Instance Main Methods java --source 22 --enable-preview Example3.java void main() { System.out.println("Hello, World!"); final Class clazz = this.getClass(); System.out.println(clazz.getName()); System.out.println(clazz.getPackage().getName()); System.out.println(clazz.getModule().getName()); } Hello, World! Example3 null Example3.java Why empty? Why null?
  • 365.
    365/466 JEP-445: Unnamed Classesand Instance Main Methods java --source 22 --enable-preview Example3.java void main() { System.out.println("Hello, World!"); final Class clazz = this.getClass(); System.out.println(clazz.getName()); System.out.println(clazz.getPackage().getName()); System.out.println(clazz.getModule().getName()); } Hello, World! Example3 null Example3.java Why empty? Why null? Using javac 22 to compile
  • 366.
    366/466 JEP-445: Unnamed Classesand Instance Main Methods  Without main() // Compiled from Example3.java (version 22 : 66.65535, super bit) final class Example3 { // Method descriptor #6 ()V // Stack: 1, Locals: 1 Example3(); 0 aload_0 [this] 1 invokespecial java.lang.Object() 4 return Line numbers: [pc: 0, line: 7] // Method descriptor #6 ()V // Stack: 2, Locals: 2 void main(); 0 getstatic java.lang.System.out : java.io.PrintStream 3 ldc <String "Hello, World!"> 5 invokevirtual java.io.PrintStream.println(java.lang.String) : void [...] 49 return [...] } Example3.java:7: error: implicitly declared class does not have main method in the form of void main() or void main(String[] args)
  • 367.
    367/466 JEP-445: Unnamed Classesand Instance Main Methods  Without main() // Compiled from Example3.java (version 22 : 66.65535, super bit) final class Example3 { // Method descriptor #6 ()V // Stack: 1, Locals: 1 Example3(); 0 aload_0 [this] 1 invokespecial java.lang.Object() 4 return Line numbers: [pc: 0, line: 7] // Method descriptor #6 ()V // Stack: 2, Locals: 2 void main(); 0 getstatic java.lang.System.out : java.io.PrintStream 3 ldc <String "Hello, World!"> 5 invokevirtual java.io.PrintStream.println(java.lang.String) : void [...] 49 return [...] } Example3.java:7: error: implicitly declared class does not have main method in the form of void main() or void main(String[] args) Autogenerated
  • 368.
    368/466 JEP-445: Unnamed Classesand Instance Main Methods  Without main() // Compiled from Example3.java (version 22 : 66.65535, super bit) final class Example3 { // Method descriptor #6 ()V // Stack: 1, Locals: 1 Example3(); 0 aload_0 [this] 1 invokespecial java.lang.Object() 4 return Line numbers: [pc: 0, line: 7] // Method descriptor #6 ()V // Stack: 2, Locals: 2 void main(); 0 getstatic java.lang.System.out : java.io.PrintStream 3 ldc <String "Hello, World!"> 5 invokevirtual java.io.PrintStream.println(java.lang.String) : void [...] 49 return [...] } Example3.java:7: error: implicitly declared class does not have main method in the form of void main() or void main(String[] args) Autogenerated Known by the JVM
  • 369.
  • 370.
  • 371.
    371/466 JEP-456: Unnamed Variablesand Patterns  Prevent unwarranted warnings final List<Order> orders = new ArrayList<>(); int total = 0; for (final Order o : orders) { total++; } System.out.println(total);
  • 372.
    372/466 JEP-456: Unnamed Variablesand Patterns  Prevent unwarranted warnings final List<Order> orders = new ArrayList<>(); int total = 0; for (final Order o : orders) { total++; } System.out.println(total); Warning: The value of the local variable o is not used
  • 373.
    373/466 JEP-456: Unnamed Variablesand Patterns  Prevent unwarranted warnings final List<Order> orders = new ArrayList<>(); int total = 0; for (final Order o : orders) { total++; } System.out.println(total); final List<Order> orders = new ArrayList<>(); int total = 0; for (final Order _ : orders) { total++; } System.out.println(total); Warning: The value of the local variable o is not used
  • 374.
    374/466 JEP-456: Unnamed Variablesand Patterns  Prevent unwarranted warnings final List<Order> orders = new ArrayList<>(); int total = 0; for (final Order o : orders) { total++; } System.out.println(total); final List<Order> orders = new ArrayList<>(); int total = 0; for (final Order _ : orders) { total++; } System.out.println(total); Warning: The value of the local variable o is not used Unnamed variable
  • 375.
  • 376.
    376/466 JEP-423: Region Pinningfor G1  Since Java 9 – G1  Since Java 10 – JEP-307  Since Java 12 – JEP-344 – JEP-346  Since Java 14 – JEP-345  Reduce latency with region pinning – GC continues even if a critical region was created by some JNI code • GetPrimitiveArrayCritical, GetStringCritical • References to arrays or Strings in the heap • References held until release functions called
  • 377.
    377/466 JEP-454: Foreign Functionand Memory API  Foreign Function and Memory (FFM) API – Productivity: replace brittle JNI with a concise, readable, and pure-Java API – Performance: access to FFM with overhead comparable to JNI (and Unsafe) – Support: discovery and invocation of native libraries on every OS with the JVM – Uniformity: operations for structured/unstructured data (no matter size, kind) – Soundness: no use-after-free bugs, even with (de)allocations by multiple threads – Integrity: warning for unsafe operations with native code and data https://www.infoq.com/news/2023/10/foreign-function-and-memory-api/
  • 378.
    378/466 JEP-454: Foreign Functionand Memory API https://www.infoq.com/news/2023/10/foreign-function-and-memory-api/ private String[] sort(final String[] strings) { final Linker linker = Linker.nativeLinker(); final SymbolLookup stdlib = linker.defaultLookup(); final MemorySegment radixSort = stdlib.find("radixsort").orElseThrow(); final MethodHandle methodHandle = linker.downcallHandle(radixSort, FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.JAVA_CHAR)); try (final Arena arena = Arena.ofConfined()) { final MemorySegment pointers = arena.allocateArray(ValueLayout.ADDRESS, strings.length); for (int i = 0; i < strings.length; i++) { final MemorySegment cString = arena.allocateUtf8String(strings[i]); pointers.setAtIndex(ValueLayout.ADDRESS, i, cString); } methodHandle.invoke(pointers, strings.length, MemorySegment.NULL, '0’); for (int i = 0; i < strings.length; i++) { MemorySegment cString = pointers.getAtIndex(ValueLayout.ADDRESS, i); cString = cString.reinterpret(Long.MAX_VALUE); strings[i] = cString.getUtf8String(0); } } catch (final Throwable e) { throw new RuntimeException(e); } return strings; }
  • 379.
  • 380.
  • 381.
  • 382.
    382/466 JEP-458: Multi-file Source-code ProgramsLaunching  Lower the (early) learning curve – But no dependency management java –cp * Prog1.java Prog1.java Prog2.java Helper.java library1.jar library2.jar
  • 383.
  • 384.
    384/466 Disclaimer  Lots ofpreview/incubating features… Some still worth mentioning! (With titles in italic)
  • 385.
  • 386.
    386/466 JEP-445: Primitive Typesin Patterns, instanceof, and switch  Systematic and consistent (everywhere?) uses of pattern-matching final int someIntValue = 42; switch (someIntValue) { case 0 -> System.out.println("Got 0"); case 1 -> System.out.println("Got 1"); case 2 -> System.out.println("Got 2"); case int i when i >= 100 -> System.out.println("Got " + i + " >= 100"); case int i -> System.out.println("Got " + i + " >2 and <100"); }
  • 387.
    387/466 JEP-445: Primitive Typesin Patterns, instanceof, and switch  Requires conversion, questions safety boolean double float long int Char short byte To → From ↓ — ɛ ɛ ɛ ɛ ωη ɛ ≈ byte — ɛ ɛ ɛ ɛ η ≈ η short — ɛ ɛ ɛ ɛ ≈ η η char — ɛ ω ɛ ≈ η η η int — ω ω ≈ η η η η long — ɛ ≈ η η η η η float — ≈ η η η η η η double ≈ — — — — — — — boolean
  • 388.
    388/466 JEP-482: Flexible Constructor Bodies “Fail Fast” class ValidationWithAuxiliaryMethod extends BigDecimal { private static long checkPositive(final long value) { if (value <= 0) throw new IllegalArgumentException("..."); return value; } public ValidationWithAuxiliaryMethod(final long value) { super(checkPositive(value)); } }
  • 389.
    389/466 JEP-482: Flexible Constructor Bodies “Fail Fast” class ValidationWithAuxiliaryMethod extends BigDecimal { private static long checkPositive(final long value) { if (value <= 0) throw new IllegalArgumentException("..."); return value; } public ValidationWithAuxiliaryMethod(final long value) { super(checkPositive(value)); } } class ValidationInConstructor extends BigInteger { public ValidationInConstructor(final long value) { if (value <= 0) throw new IllegalArgumentException("..."); super(value); ...
  • 390.
  • 391.
    391/466 JEP-474: ZGC: GenerationalMode by Default  What can I say?
  • 392.
  • 393.
    393/466 JEP-466: Class-File API Manipulate class-files directly in Java ClassFile.of().buildTo(Path.of("A.class"), ClassDesc.of("A"), classBuilder -> classBuilder.withMethod("fooBar", MethodTypeDesc.of(CD_void, CD_boolean, CD_int), AccessFlags.ofMethod(AccessFlag.PUBLIC).flagsMask(), methodBuilder -> methodBuilder.withCode(codeBuilder -> { final Label label1 = codeBuilder.newLabel(); final Label label2 = codeBuilder.newLabel(); codeBuilder.iload(1).ifeq(label1).aload(0).iload(2) .invokevirtual(ClassDesc.of("Foo"), "foo", MethodTypeDesc.of(CD_void, CD_int)) .goto_(label2).labelBinding(label1).aload(0) .iload(2) .invokevirtual(ClassDesc.of("Foo"), "bar", MethodTypeDesc.of(CD_void, CD_int)) .labelBinding(label2).return_(); })));
  • 394.
    394/466 JEP-469: Vector API “Introduce an API to express vector computations that reliably compile at runtime to optimal vector instructions on supported CPU architectures, thus achieving performance superior to equivalent scalar computations.”
  • 395.
    395/466 JEP-469: Vector API staticfinal VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED; void vectorComputation(float[] a, float[] b, float[] c) { int i = 0; int upperBound = SPECIES.loopBound(a.length); for (; i < upperBound; i += SPECIES.length()) { // FloatVector va, vb, vc; var va = FloatVector.fromArray(SPECIES, a, i); var vb = FloatVector.fromArray(SPECIES, b, i); var vc = va.mul(va).add(vb.mul(vb)).neg(); vc.intoArray(c, i); } for (; i < a.length; i++) { c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f; } }
  • 396.
    396/466 JEP-476: Module Import Declarations Simplify the use of modules import module M1; public class Example1 { ... module M1 { exports p1; exports p2 to M0; exports p3 to M3; requires transitive M4; requires M5; } module M3 { ... } module M4 { exports p10; } module M5 { exports p11; }
  • 397.
    397/466 JEP-476: Module Import Declarations Simplify the use of modules import module M1; public class Example1 { ... module M1 { exports p1; exports p2 to M0; exports p3 to M3; requires transitive M4; requires M5; } module M3 { ... } module M4 { exports p10; } module M5 { exports p11; }
  • 398.
    398/466 JEP-476: Module Import Declarations Simplify the use of modules import module M1; public class Example1 { ... module M1 { exports p1; exports p2 to M0; exports p3 to M3; requires transitive M4; requires M5; } module M3 { ... } module M4 { exports p10; } module M5 { exports p11; }
  • 399.
    399/466 JEP-476: Module Import Declarations Simplify the use of modules import module M1; public class Example1 { ... module M1 { exports p1; exports p2 to M0; exports p3 to M3; requires transitive M4; requires M5; } module M3 { ... } module M4 { exports p10; } module M5 { exports p11; }
  • 400.
    400/466 JEP-481: Scoped Values Client-dependent context  Alternative to ThreadLocal class Framework { private final static ScopedValue<FrameworkContext> CONTEXT = ScopedValue.newInstance(); void serve(Request request, Response response) { var context = createContext(request); ScopedValue.runWhere(CONTEXT, context, () -> Application.handle(request, response)); } public PersistedObject readKey(String key) { var context = CONTEXT.get(); var db = getDBConnection(context); db.readKey(key); ...
  • 401.
  • 402.
    402/466 JEP-471: Deprecate theMemory- Access Methods for Removal class OffHeapArray { private final static int BYTE_SIZE = 1; private long size; private long address; public OffHeapArray(final long size) throws ... { this.size = size; this.address = this.getUnsafe().allocateMemory(this.size * BYTE_SIZE); } private Unsafe getUnsafe() throws ... { final Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); return (Unsafe) f.get(null); } public void set(final long idx, final byte value) throws ... { this.getUnsafe().putByte(this.address + idx * BYTE_SIZE, value); } public int get(final long idx) throws ... { return this.getUnsafe().getByte(this.address + idx * BYTE_SIZE); } public void freeMemory() throws ... { this.getUnsafe().freeMemory(this.address); } ...
  • 403.
    403/466 JEP-471: Deprecate theMemory- Access Methods for Removal final OffHeapArray oha = new OffHeapArray(3); oha.set(0, (byte) 42); oha.set(1, (byte) 84); oha.set(2, (byte) 111); System.out.println(oha.get(0)); System.out.println(oha.get(1)); System.out.println(oha.get(2)); oha.freeMemory();
  • 404.
    404/466 JEP-471: Deprecate theMemory- Access Methods for Removal final OffHeapArray oha = new OffHeapArray(3); oha.set(0, (byte) 42); oha.set(1, (byte) 84); oha.set(2, (byte) 111); System.out.println(oha.get(0)); System.out.println(oha.get(1)); System.out.println(oha.get(2)); oha.freeMemory(); final OffHeapArray oha = new OffHeapArray(1); oha.set(0, (byte) 42); oha.set(1, (byte) 84); oha.set(2, (byte) 111); System.out.println(oha.get(0)); System.out.println(oha.get(1)); System.out.println(oha.get(2)); oha.freeMemory(); Where am I writing?
  • 405.
    405/466 JEP-477: Implicitly DeclaredClasses and Instance Main Methods  Java Python-isation continues… – “thereby avoiding the mysterious System.out.println” public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }
  • 406.
    406/466 JEP-477: Implicitly DeclaredClasses and Instance Main Methods  Java Python-isation continues… – “thereby avoiding the mysterious System.out.println” public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } } class HelloWorld { void main() { System.out.println("Hello, World!"); } }
  • 407.
    407/466 JEP-477: Implicitly DeclaredClasses and Instance Main Methods  Java Python-isation continues… – “thereby avoiding the mysterious System.out.println” public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } } class HelloWorld { void main() { System.out.println("Hello, World!"); } } void main() { System.out.println("Hello, World!"); }
  • 408.
    408/466 JEP-477: Implicitly DeclaredClasses and Instance Main Methods  Java Python-isation continues… – “thereby avoiding the mysterious System.out.println” public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } } class HelloWorld { void main() { System.out.println("Hello, World!"); } } void main() { println("Hello, World!"); } void main() { System.out.println("Hello, World!"); }
  • 409.
  • 410.
  • 411.
    411/466 Language  Some previewfeatures… Some still worth mentioning!
  • 412.
    412/466 Language  JEP-487: ScopedValues – Fourth Preview  JEP-488: Primitive Types in Patterns, instanceof, and switch – Second Preview  JEP-492: Flexible Constructor Bodies – Third Preview  JEP-494: Module Import Declarations – Second Preview
  • 413.
  • 414.
    414/466 JEP-475: Late BarrierExpansion for G1  Reduces overall JVM overhead – For optimising JIT compilers, e.g., JDK’s C2  Expanding G1 barriers early increases C2 overhead by 10-20%
  • 415.
  • 416.
  • 417.
    417/466 JEP-490: ZGC: Removethe Non- Generational Mode  Remove the non-generational mode 
  • 418.
    418/466 JEP-490: ZGC: Removethe Non- Generational Mode  Remove the non-generational mode  What can I say?
  • 419.
    419/466 JEP-483: Ahead-of-Time Class Loadingand Linking  Most applications start up follow the same steps every time they run  Extend the HotSpot JVM to support an ahead-of-time cache – Evolution of class-data sharing
  • 420.
    420/466 JEP-483: Ahead-of-Time Class Loadingand Linking  Requires three steps – Training run – Cache creation – Cache utilisation $ java -cp bin/ net.ptidej.newjava.aotcache.Main Some application doing lots of things at start up... $ java - - - -XX:AOTMode=record XX:AOTMode=record XX:AOTMode=record XX:AOTMode=record - - - -XX:AOTConfiguration=app.aotconf XX:AOTConfiguration=app.aotconf XX:AOTConfiguration=app.aotconf XX:AOTConfiguration=app.aotconf -cp bin/ net.ptidej.newjava.aotcache.Main Some application doing lots of things at start up... $ java - - - -XX:AOTMode=create XX:AOTMode=create XX:AOTMode=create XX:AOTMode=create - - - -XX:AOTConfiguration=app.aotconf XX:AOTConfiguration=app.aotconf XX:AOTConfiguration=app.aotconf XX:AOTConfiguration=app.aotconf - - - -XX:AOTCache=app.aot XX:AOTCache=app.aot XX:AOTCache=app.aot XX:AOTCache=app.aot -cp bin/ net.ptidej.newjava.aotcache.Main [0.237s][warning][cds] Skipping net/.../Main: Unsupported location AOTCache creation is complete: app.aot $ java - - - -XX:AOTCache=app.aot XX:AOTCache=app.aot XX:AOTCache=app.aot XX:AOTCache=app.aot -cp bin/ net.ptidej.newjava.aotcache.Main Some application doing lots of things at start up...
  • 421.
    421/466 JEP-483: Ahead-of-Time Class Loadingand Linking  Creates two new files – An AOT file • Very large, binary file • Classes are available instantly from it – An AOT configuration file • Text file $ java -cp bin/ net.ptidej.newjava.aotcache.Main Some application doing lots of things at start up... $ ll total 4.1M -r--r--r-- 1 yann None 9.0M 9.0M 9.0M 9.0M Mar 19 22:10 app.aot -rw-r--r-- 1 yann None 42K 42K 42K 42K Mar 19 22:09 app.aotconf drwxr-xr-x 1 yann None 0 Mar 19 22:08 bin/ drwxr-xr-x 1 yann None 0 Mar 19 22:08 src/
  • 422.
    422/466 JEP-483: Ahead-of-Time Class Loadingand Linking  Example of Spring PetClinic (!) – Version 3.2.0 – Loads and links ~21,000 classes – Startup times • Without AOT cache 4.486s (JDK 23) • With AOT cache 2.604s (JDK 24, 42%)
  • 423.
    423/466 JEP-491: Synchronize Virtual Threadswithout Pinning  Virtual threads  Platform threads  Arrange “for virtual threads that block in [synchronized methods and blocks] to release their underlying platform threads”
  • 424.
  • 425.
    425/466 JEP-484: Class-File API Non-goals – “[O]bsolete existing libraries [for] class files” • Apache BCEL • IBM CFParse – “[E]xtend the Core Reflection API to give access to the bytecode of loaded classes.” • Would require changes to the JVM – “[P]rovide code analysis functionality” • Should be provided by third-party libraries
  • 426.
    426/466 JEP-484: Class-File API Manipulate class-files directly in Java ClassFile.of().buildTo(Path.of("A.class"), ClassDesc.of("A"), classBuilder -> classBuilder.withMethod("fooBar", MethodTypeDesc.of(CD_void, CD_boolean, CD_int), AccessFlags.ofMethod(AccessFlag.PUBLIC).flagsMask(), methodBuilder -> methodBuilder.withCode(codeBuilder -> { final Label label1 = codeBuilder.newLabel(); final Label label2 = codeBuilder.newLabel(); codeBuilder.iload(1).ifeq(label1).aload(0).iload(2) .invokevirtual(ClassDesc.of("Foo"), "foo", MethodTypeDesc.of(CD_void, CD_int)) .goto_(label2).labelBinding(label1).aload(0) .iload(2) .invokevirtual(ClassDesc.of("Foo"), "bar", MethodTypeDesc.of(CD_void, CD_int)) .labelBinding(label2).return_(); })));
  • 427.
    427/466 JEP-485: Stream Gatherers Map-Reduce – Processing, generating large data sets – Parallel and distributed  Streaming platforms – Unified, high-throughput, low-latency – Apache Kafka  Sequence of data – Declarative, functional – Parallel and distributed https://www.oracle.com/technical-resources/articles/java/ma14-java-se-8-streams.html
  • 428.
  • 429.
    429/466 JEP-485: Stream Gatherers privatestatic final record Transaction(Type type, int id, int value) { enum Type { GROCERY, ENTERTAINMENT; } public Type getType() { return this.type; } public int getValue() { return this.value; } public int getId() { return this.id; } } public static void main(final String[] args) { final List<Transaction> transactions = List.of( new Transaction(Transaction.Type.ENTERTAINMENT, 1, 100), new Transaction(Transaction.Type.GROCERY, 3, 80), new Transaction(Transaction.Type.GROCERY, 6, 120), new Transaction(Transaction.Type.ENTERTAINMENT, 7, 40), new Transaction(Transaction.Type.GROCERY, 10, 50)); final List<Integer> transactionsIds = transactions.parallelStream() .filter(t -> t.getType() == Transaction.Type.GROCERY) .sorted(Comparator.comparing(Transaction::getValue).reversed()) .map(Transaction::getId).collect(Collectors.toList()); System.out.println(transactionsIds); }
  • 430.
    430/466 JEP-485: Stream Gatherers privatestatic final record Transaction(Type type, int id, int value) { enum Type { GROCERY, ENTERTAINMENT; } public Type getType() { return this.type; } public int getValue() { return this.value; } public int getId() { return this.id; } } public static void main(final String[] args) { final List<Transaction> transactions = List.of( new Transaction(Transaction.Type.ENTERTAINMENT, 1, 100), new Transaction(Transaction.Type.GROCERY, 3, 80), new Transaction(Transaction.Type.GROCERY, 6, 120), new Transaction(Transaction.Type.ENTERTAINMENT, 7, 40), new Transaction(Transaction.Type.GROCERY, 10, 50)); final List<Integer> transactionsIds = transactions.parallelStream() .filter(t -> t.getType() == Transaction.Type.GROCERY) .sorted(Comparator.comparing(Transaction::getValue).reversed()) .map(Transaction::getId).collect(Collectors.toList()); System.out.println(transactionsIds); } [6, 3, 10]
  • 431.
    431/466 JEP-485: Stream Gatherers Stateless vs. Stateful methods – filter() and map() – distinct() and sorted() • limit() cuts short the processing https://www.logicbig.com/tutorials/core-java-tutorial/java-util-stream/stream-cheat-sheet.html
  • 432.
    432/466 JEP-485: Stream Gatherers In particular – distinct() uses equals() – E.g., String content  @Override public void accept(T t) { if (t == null) { if (!seenNull) { seenNull = true; downstream.accept(lastSeen = null); } } else if (lastSeen == null || !t.equals(lastSeen)) { downstream.accept(lastSeen = t); } }
  • 433.
    433/466 JEP-485: Stream Gatherers In particular – distinct() uses equals() – E.g., String content  @Override public void accept(T t) { if (t == null) { if (!seenNull) { seenNull = true; downstream.accept(lastSeen = null); } } else if (lastSeen == null || !t.equals(lastSeen)) { downstream.accept(lastSeen = t); } } Object::equals()
  • 434.
    434/466 JEP-485: Stream Gatherers In particular – distinct() uses equals() – E.g., String content  What if we want String length? @Override public void accept(T t) { if (t == null) { if (!seenNull) { seenNull = true; downstream.accept(lastSeen = null); } } else if (lastSeen == null || !t.equals(lastSeen)) { downstream.accept(lastSeen = t); } } Object::equals()
  • 435.
    435/466 JEP-485: Stream Gatherers Before, only equals()  Now, any method and stateful object final List<String> result = Stream .of("foo", "bar", "bar", "bar", "zorg") .distinct() .toList(); final DifferentLength differentLength = new DifferentLength(); final List<String> result = Stream .of("foo", "bar", "bar", "bar", "zorg") .gather(Gatherer.ofSequential( Integrator.ofGreedy(differentLength))) .toList();
  • 436.
    436/466 JEP-485: Stream Gatherers Or all-in-one final List<String> result = Stream .of("foo", "bar", "bar", "bar", "zorg") .gather(Gatherer.ofSequential( DifferentLength::new, Integrator.ofGreedy(DifferentLength::integrate), DifferentLength::finish)) .toList();
  • 437.
    437/466 JEP-485: Stream Gatherers classDifferentLength { private final Set<Integer> setOfLengths; DifferentLength() {this.setOfLengths = new HashSet<>(); } boolean integrate( final String element,final Downstream<? super String> downstream) { final int length = element.length(); if (!setOfLengths.contains(length)) { setOfLengths.add(length); return downstream.push(element); } return true; } void finish(final Downstream<? super String> downstream) { } } final List<String> result = Stream .of("foo", "bar", "bar", "bar", "zorg") .gather(Gatherer.<String, DifferentLength, String>ofSequential( DifferentLength::new, Integrator.<DifferentLength, String, String>ofGreedy(DifferentLength::integrate), DifferentLength::finish)) .toList();
  • 438.
    438/466 JEP-485: Stream Gatherers classDifferentLength { private final Set<Integer> setOfLengths; DifferentLength() {this.setOfLengths = new HashSet<>(); } boolean integrate( final String element,final Downstream<? super String> downstream) { final int length = element.length(); if (!setOfLengths.contains(length)) { setOfLengths.add(length); return downstream.push(element); } return true; } void finish(final Downstream<? super String> downstream) { } } final List<String> result = Stream .of("foo", "bar", "bar", "bar", "zorg") .gather(Gatherer.<String, DifferentLength, String>ofSequential( DifferentLength::new, Integrator.<DifferentLength, String, String>ofGreedy(DifferentLength::integrate), DifferentLength::finish)) .toList(); Any desired state!
  • 439.
    439/466 JEP-485: Stream Gatherers classDifferentLength { private final Set<Integer> setOfLengths; DifferentLength() {this.setOfLengths = new HashSet<>(); } boolean integrate( final String element,final Downstream<? super String> downstream) { final int length = element.length(); if (!setOfLengths.contains(length)) { setOfLengths.add(length); return downstream.push(element); } return true; } void finish(final Downstream<? super String> downstream) { } } final List<String> result = Stream .of("foo", "bar", "bar", "bar", "zorg") .gather(Gatherer.<String, DifferentLength, String>ofSequential( DifferentLength::new, Integrator.<DifferentLength, String, String>ofGreedy(DifferentLength::integrate), DifferentLength::finish)) .toList(); Any desired state! Not very clear…
  • 440.
    440/466 JEP-485: Stream Gatherers The optional initialiser function provides an object that maintains private state  The integrator function integrates a new element from the input stream  The optional combiner function can evaluate the gatherer in parallel for parallel streams  The optional finisher function is called when there are no more input elements
  • 441.
    441/466 JEP-496: Quantum-Resistant Module-Lattice-Based Key EncapsulationMechanism JEP-497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm  Post-quantum cryptography – Algorithms secured against a cryptanalytic attack by a quantum computer
  • 442.
  • 443.
    443/466 JEP-496 and JEP-497 Six main approaches 1. Lattice-based cryptography 2. Multivariate cryptography 3. Hash-based cryptography 4. Code-based cryptography 5. Isogeny-based cryptography 6. Symmetric key quantum resistance
  • 444.
    444/466 JEP-496 and JEP-497 Six main approaches 1. Lattice-based cryptography 2. Multivariate cryptography 3. Hash-based cryptography 4. Code-based cryptography 5. Isogeny-based cryptography 6. Symmetric key quantum resistance
  • 445.
    445/466 JEP-496 and JEP-497 finalKeyPairGenerator kpgKEM = KeyPairGenerator.getInstance("ML-KEM"); kpgKEM.initialize(NamedParameterSpec.ML_KEM_512); final KeyPair kpKEM = kpgKEM.generateKeyPair(); // an ML-KEM-512 key pair System.out.println(kpKEM.getPrivate()); System.out.println(kpKEM.getPublic()); final KeyPairGenerator kpgDSA = KeyPairGenerator.getInstance("ML-DSA"); kpgDSA.initialize(NamedParameterSpec.ML_DSA_44); final KeyPair kpDSA = kpgDSA.generateKeyPair(); // an ML-DSA-44 key pair System.out.println(kpDSA.getPrivate()); System.out.println(kpDSA.getPublic());
  • 446.
    446/466 JEP-498: Warn uponUse of Memory- Access Methods in sun.misc.Unsafe  Now in module jdk.unsupported  79 out of 87 methods for accessing memory – JVM’s garbage-collected heap – Off-heap memory (out of the JVM’s control)
  • 447.
    447/466 JEP-498: Warn uponUse of Memory- Access Methods in sun.misc.Unsafe  java.lang.invoke.VarHandle – JDK 9 (JEP-193) – Safely and efficiently access on-heap memory, i.e., fields of objects, fields of classes…  java.lang.foreign.MemorySegment – JDK 22 (JEP-454) – Safely and efficiently access off-heap memory, c.f., Project Panama
  • 448.
    448/466 JEP-498: Warn uponUse of Memory- Access Methods in sun.misc.Unsafe  JDK 24: Warning  JDK 26+: Exception  JDK 27+: Removal of methods that have standard and safe alternatives WARNING: A terminally deprecated method in sun.misc.Unsafe has been called WARNING: sun.misc.Unsafe::setMemory has been called by com.foo.bar.Server (file:/tmp/foobarserver/thing.jar) WARNING: Please consider reporting this to the maintainers of com.foo.bar.Server WARNING: sun.misc.Unsafe::setMemory will be removed in a future release
  • 449.
  • 450.
    450/466 JEP-472: Prepare toRestrict the Use of JNI  Want integrity by default – “[A]ll JDK features that are capable of breaking integrity must obtain explicit approval from the application's developer.”
  • 451.
    451/466 JEP-472: Prepare toRestrict the Use of JNI 1. Long values as addresses in memory 2. Byte buffers starting at address 0 3. Modifying immutable objects (e.g., Strings) 4. Writing past the end of an array 5. Using functions disturbing the GC
  • 452.
    452/466 JEP-472: Prepare toRestrict the Use of JNI 1. Long values as addresses in memory void Java_pkg_C_setPointerToThree__J(jlong ptr) { *(int*)ptr = 3; }
  • 453.
    453/466 JEP-472: Prepare toRestrict the Use of JNI 2. Byte buffers starting at address 0 return (*env)->NewDirectByteBuffer(env, 0, 10);
  • 454.
    454/466 JEP-472: Prepare toRestrict the Use of JNI 3. Modifying immutable objects jclass clazz = (*env)->FindClass(env, "java/lang/String"); jfieldID fid = (*env)->GetFieldID(env, clazz , "value", "[B"); jbyteArray contents = (jbyteArray)(*env)->GetObjectField(env, str, fid); jbyte b = 0; (*env)->SetByteArrayRegion(env, contents, 0, 1, &b);
  • 455.
    455/466 JEP-472: Prepare toRestrict the Use of JNI 4. Writing past the end of an array jbyte *a = (*env)->GetPrimitiveArrayCritical(env, arr, 0); a[500] = 3; // May be out of bounds (*env)->ReleasePrimitiveArrayCritical(env, arr, a, 0);
  • 456.
    456/466 JEP-472: Prepare toRestrict the Use of JNI 5. Using functions disturbing the GC “However, there are significant restrictions on how these functions can be used.” https://shipilev.net/jvm/anatomy-quarks/9-jni-critical-gclocker/
  • 457.
    457/466 JEP-472: Prepare toRestrict the Use of JNI  “Under the policy of integrity by default, it is the application developer (or perhaps deployer, on the advice of the application developer) who enables native access”
  • 458.
    458/466 JEP-472: Prepare toRestrict the Use of JNI  “Under the policy of integrity by default, it is the application developer (or perhaps deployer, on the advice of the application developer) who enables native access” WARNING: A restricted method in java.lang.System has been called WARNING: java.lang.System::loadLibrary has been called by net.ptidej.newjava.restrictJNI.Main in module myModule (file:...) WARNING: Use --enable-native-access=myModule to avoid a warning for callers in this module WARNING: Restricted methods will be blocked in a future release unless native access is enabled
  • 459.
    459/466 JEP-479: Remove theWindows 32-bit x86 Port  “Allow contributors in the OpenJDK Community to accelerate […] development”  “JEP 436 (Virtual Threads) for Windows x86- 32 falls back [on] kernel threads [removing the] benefits of Project Loom.”  “Windows 10, the last Windows operating system to support 32-bit operation, will reach End of Life in October 2025.”
  • 460.
    460/466 JEP-479: Remove theWindows 32-bit x86 Port  Also related to JEP-501: Deprecate the 32- bit x86 Port for Removal – Linux 32-bit x86 port
  • 461.
    461/466 JEP-486: Permanently Disablethe Security Manager  “[T]he permission scheme is so complex that the Security Manager has always been disabled by default, and its use is […] rare.”  “From networking, I/O, and JDBC, to XML, AWT, and Swing, the libraries must implement the least-privilege model in case the Security Manager is enabled” Emphasis mine
  • 462.
    462/466 JEP-486: Permanently Disablethe Security Manager  “[T]he permission scheme is so complex that the Security Manager has always been disabled by default, and its use is […] rare.”  “From networking, I/O, and JDBC, to XML, AWT, and Swing, the libraries must implement the least-privilege model in case the Security Manager is enabled” Emphasis mine
  • 463.
    463/466 JEP-486: Permanently Disablethe Security Manager  “Over 1,000 methods must check for permission”  “Over 1,200 methods must elevate their privileges”  If needed, can be replaced outside of JVM – An agent can block code from calling System::exit
  • 464.
    464/466 JEP-493: Linking Run-TimeImages without JMODs  “Reduce the size of the JDK by […] 25% by enabling the jlink tool to create custom run-time images without using the JDK's JMOD files.” – JMOD is JAR with native code, configuration files, and other kinds of data
  • 465.
  • 466.
    466/466 Image Credits  Disclaimer:https://www.elitelux.club/understanding-java-programming/  Organisation: https://www.comsoftit.com/web.html  Java 5&6: https://www.amazon.ca/JAVA-SYNTHESE-COURS-EXERCICES-CORRIGES/dp/2744072192  Java 7: https://www.gizchina.com/2022/07/31/java-7-se-reaches-a-dead-end-java-8-becomes-the-norm/  Java 8: https://www.infoworld.com/article/3676578/oracle-unveils-performance-pack-for-java-8.html  Java 9: https://fossbytes.com/java-9-is-coming-release-date-features/  Java 10: https://codepumpkin.com/java-10-features/  Java 11: https://www.amazon.ca/Mastering-Java-Second-Edward-Lavieri/dp/1789137616  Java 12: https://loiane.com/2019/03/what-is-new-in-java-12-api-for-developers/  https://www.neosoft.fr/nos-publications/blog-tech/benchmark-java-introduction-a-jmh/  Java 13: https://java-13.com/  Java 14: https://dzone.com/refcardz/java-14-1  Java 15: https://dev.to/aaiezza/are-you-seriously-not-using-java-15-yet-5c86  Java 16: https://www.azul.com/blog/67-new-features-in-jdk-16/  Java 17: https://www.codingknownsense.com/clear-your-concept/java-17-a-brief-overview-of-features-and-enhancements/  Java 18: https://twitter.com/Sharat_Chander/status/1506279732094148627  Java 19: https://medium.com/codex/java-19-the-new-features-1bb1b6bed83c  https://wiki.openjdk.org/display/duke/Gallery  https://guigarage.com/  Java 20: https://dev.to/symflower/what-is-new-in-java-20-21gh  Java 21: https://www.unlogged.io/post/all-you-need-to-know-about-java21  Java 22: https://www.makb183.com/2023/10/java-22-what-to-expect.html  Eager: https://www.facebook.com/eagertolearnJava/  https://superacpov.live/product_details/50265612.html  https://www.istockphoto.com/search/2/image?mediatype=illustration&phrase=warning+road+signs  Java 23: https://www.heise.de/news/Java-23-erweitert-Import-und-Patterns-verzichtet-aber-auf-String-Templates-9870591.html  Java 24: https://www.oracle.com/news/announcement/oracle-releases-java-24-2025-03-18/  https://tenor.com/en-GB/view/the-simpsons-homer-bush-disappear-awkward-gif-4841810