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