Advertisement

Deep Dive Java 17 Devoxx UK

Maître de conférences, JEE architecte expert consultant at Université Paris 13 Nord
Nov. 3, 2021
Advertisement

More Related Content

Advertisement
Advertisement

Deep Dive Java 17 Devoxx UK

  1. Java 17: Deep Dive José Paumard Java Developer Advocate Java Platform Group
  2. https://twitter.com/JosePaumard https://github.com/JosePaumard https://www.youtube.com/c/JosePaumard01 https://www.youtube.com/user/java https://www.youtube.com/hashtag/jepcafe https://fr.slideshare.net/jpaumard https://www.pluralsight.com/authors/jose-paumard https://jchateau.org
  3. https://twitter.com/JosePaumard https://github.com/JosePaumard https://www.youtube.com/c/JosePaumard01 https://www.youtube.com/user/java https://www.youtube.com/hashtag/jepcafe https://fr.slideshare.net/jpaumard https://www.pluralsight.com/authors/jose-paumard https://dev.java
  4. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 4 Dev.java Java 8 Java 11
  5. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 5 Java 17 – LTS ! Java 8 Java 11
  6. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 6 OpenJDK? https://openjdk.java.net
  7. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 7 New Release Cadence! 11 12 13 14 15 16 17 18 19 20 21 22 23 2018 2019 2020 2021 2022 2023 2024 2025 http://jdk.java.net/
  8. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 8 New Release Cadence! 11 12 13 14 15 16 17 18 19 20 21 22 http://jdk.java.net/ 23 2018 2019 2020 2021 2022 2023 2024 2025
  9. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 9 New Release Cadence! 11 12 13 14 15 16 17 18 19 20 21 22 https://www.oracle.com/java/ technologies/javase- downloads.html 23 2018 2019 2020 2021 2022 2023 2024 2025
  10. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 10 New New Release Cadence! 11 12 13 14 15 16 17 18 19 20 21 22 1) LTS: 3 years  2 years 23 2018 2019 2020 2021 2022 2023 2024 2025 https://mreinhold.org/blog/forward-even-faster https://blogs.oracle.com/java/post/ moving-the-jdk-to-a-two-year-lts-cadence
  11. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 11 New New Release Cadence! 11 12 13 14 15 16 17 18 19 20 21 22 2018 2019 2020 2021 2022 2023 2024 2025 23 1) LTS: 3 years  2 years https://mreinhold.org/blog/forward-even-faster https://blogs.oracle.com/java/post/ moving-the-jdk-to-a-two-year-lts-cadence
  12. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 12 New New Release Cadence! 11 12 13 14 15 16 17 18 19 20 21 22 2018 2019 2020 2021 2022 2023 2024 2025 23 1) LTS: 3 years  2 years 2) Free licence (dev + prod) 3) No click-through https://blogs.oracle.com/java/post/ free-java-license
  13. Sept. 2021 Mars 2014 4 Years 90 80 70 60 50 40 30 20 10 0 56 91 12 17 8 5 16 14 17 14 Mars 2018 3 Years JDK 8 LTS JDK 9-11 JDK 12-17 JDK 9 JDK 10 JDK 11 LTS JDK 12 JDK 13 JDK 14 JDK 15 JDK 16 JDK 17 LTS Features From 8 to 17 Copyright © 2021, Oracle and/or its affiliates 13
  14. Language Type inference for locals (var) Switch expressions Text blocks Record classes Sealed classes Pattern matching for instanceof JDK 17: New Features Since the JDK 8 Copyright © 2021, Oracle and/or its affiliates 14 Tools jshell jlink jdeps jpackage java source code launcher javadoc search + API history JVM Garbage Collectors: G1, ZGC AArch64 support: Windows, Mac, Linux Docker awareness Class Data Sharing by default Helpful NullPointerExceptions Hidden classes Libraries HTTP client Collection factories Unix-domain sockets Stack walker Deserialization filtering Pseudo-RNG, SHA-3, TLS 1.3
  15. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted 15 Tools
  16. Language Type inference for locals (var) Switch expressions Text blocks Record classes Sealed classes Pattern matching for instanceof JDK 17: New Features Since the JDK 8 Copyright © 2021, Oracle and/or its affiliates 16 Tools jshell jlink jdeps jpackage java source code launcher javadoc search + API history JVM Garbage Collectors: G1, ZGC AArch64 support: Windows, Mac, Linux Docker awareness Class Data Sharing by default Helpful NullPointerExceptions Hidden classes Libraries HTTP client Collection factories Unix-domain sockets Stack walker Deserialization filtering Pseudo-RNG, SHA-3, TLS 1.3 Tools jshell jlink jdeps jpackage java source code launcher javadoc search + API history
  17. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 17 Step 1: Hello World Launching Single File Source Code public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } } $ java HelloWorld.java
  18. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 18 Step 2: Add 3rd party dependencies Launching Single File Source Code public class HelloWorld { public static void main(String[] args) { System.out.println(RandomUtils.nextInt()); } } $ java -cp /path/to/commons-lang3-3.12.0.jar HelloWorld.java
  19. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 19 Step 3: Execute a shebang file Launching Single File Source Code #!/path/to/your/bin/java --source 17 public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } } $ ./HelloWorld
  20. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 20 Create a runtime image JLink: Creating Custom Runtime Images $ jlink --module-path mods --add-modules org.mycompany.mymodule --output myapp-image
  21. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 21 Create a runtime image with a launcher JLink: Creating Custom Runtime Images # create the image $ jlink --module-path mods --add-modules com.example.main --launcher app=com.example.app/com.example.app.Main --output app-image # launch $ app-image/bin/app
  22. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 22 The smallest runtime image JLink: Creating Custom Runtime Images $ jlink --add-modules java.base --output jdk.base $ du –sh jdk.base jdk-17 40M jdk.base 288M jdk-17
  23. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 23 Supported Installers: MSI, EXE, RPM, DEB, PKG, DMG JPackage: Creating Custom Installers $ jpackage --name my-installer --app-version 1.0 --win-dir-chooser --win-console --win-shortcut --module-path mymodules/my-app-1.0.jar --module org.myapp/org.mycompany.myapp.MainClass
  24. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted 24 API
  25. Language Type inference for locals (var) Switch expressions Text blocks Record classes Sealed classes Pattern matching for instanceof JDK 17: New Features Since the JDK 8 Copyright © 2021, Oracle and/or its affiliates 25 Tools jshell jlink jdeps jpackage java source code launcher javadoc search + API history JVM Garbage Collectors: G1, ZGC AArch64 support: Windows, Mac, Linux Docker awareness Class Data Sharing by default Helpful NullPointerExceptions Hidden classes Libraries HTTP client Collection factories Unix-domain sockets Stack walker Deserialization filtering Pseudo-RNG, SHA-3, TLS 1.3 Libraries HTTP client Collection factories Unix-domain sockets Stack walker Deserialization filtering Pseudo-RNG, SHA-3, TLS 1.3
  26. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 26 Step 1: create a request HttpClient API HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://example.com")) .header("Accept-Encoding", "gzip") .header("Accept", "text/xml") .GET() .build();
  27. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 27 Step 2: create a client HttpClient API HttpClient client = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_1_1) .connectTimeout(Duration.ofSeconds(20)) .build();
  28. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 28 Step 3: send the request HttpClient API HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream()); InputStream inputStream = response.body();
  29. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 29 Step 3: send the request HttpClient API HttpResponse<Stream<String>> response = client.send(request, HttpResponse.BodyHandlers.ofLines()); Stream<String> lines = response.body();
  30. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 30 Open a web server for serving a single directory hierarchy. Options: Simple HttpServer: Command Line Tool & API $ java -m jdk.httpserver -b, --bind-address - Address to bind to. Default: 127.0.0.1 or ::1 (loopback). For all interfaces use "-b 0.0.0.0" or "-b ::". -d, --directory - Directory to serve. Default: current directory. -o, --output - Output format. none|info|verbose. Default: info. -p, --port - Port to listen on. Default: 8000.
  31. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 31 The API version, in JShell Supports HTTP only, request handling can be customized Simple HttpServer: Command Line Tool & API jshell> var server = SimpleFileServer.createFileServer( > new InetSocketAddress(8080), > Path.of("/some/path"), > OutputLevel.VERBOSE); jshell> server.start()
  32. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 32 Supported on Linux, MacOS and some flavors of Windows Both on the server and the client Unix Domain Sockets Path home = Path.of("/tmp"); Path file = home.resolve("user.socket"); UnixDomainSocketAddress socketAddress = UnixDomainSocketAddress.of(file);
  33. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 33 On the server: On the client: Unix Domain Sockets ServerSocketChannel channel = ServerSocketChannel.open(StandardProtocolFamily.UNIX); SocketChannel socketChannel = channel.bind(socketAddress).accept(); SocketChannel socketChannel = SocketChannel.open(socketAddress);
  34. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 34 Current status: getting the execution stack is costly, it captures the entire stack (getStackTrace() on Thread and Throwable) Sometimes you only need the first elements of the stack Idea: have a way of lazily explore the stack, based on a Stream<StackFrame> and a callback Stack Frame Walker
  35. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 35 Stack Frame Walker StackWalker walker = StackWalker.getInstance( StackWalker.Option.RETAIN_CLASS_REFERENCE); walker.forEach( stackFrame -> System.out.println(stackFrame.getClassName()));
  36. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 36 Stack Frame Walker Set<String> classNames = ...; Optional<String> className = walker.walk( stackFrameStream -> stackFrameStream .map(StackWalker.StackFrame::getClassName) .filter(classNames::contains) .findFirst() );
  37. Language Type inference for locals (var) Switch expressions Text blocks Record classes Sealed classes Pattern matching for instanceof JDK 17: New Features Since the JDK 8 Copyright © 2021, Oracle and/or its affiliates 37 Tools jshell jlink jdeps jpackage java source code launcher javadoc search + API history JVM Garbage Collectors: G1, ZGC AArch64 support: Windows, Mac, Linux Docker awareness Class Data Sharing by default Helpful NullPointerExceptions Hidden classes Libraries HTTP client Collection factories Unix-domain sockets Stack walker Deserialization filtering Pseudo-RNG, SHA-3, TLS 1.3 Language Type inference for locals (var) Switch expressions Text blocks Record classes Sealed classes Pattern matching for instanceof
  38. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 38 Do not override finalize() Stop doing that! @Deprecated(since="9") protected void finalize() throws Throwable { }
  39. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 39 Do not call new Integer(...) Stop doing that! @Deprecated(since="9", forRemoval = true) public Integer(int value) { this.value = value; } @IntrinsicCandidate public static Integer valueOf(int i) { // some code return new Integer(i); }
  40. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 40 ☕ Coffee Break!
  41. Record and Array Pattern Matching Record Sealed Classes Switch Expression Constant Dynamic Inner Classes private in VM Nestmates Pattern Matching for instanceof 11 14 16 17 Switch on Patterns 18
  42. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 42 In reference to the Amber by Roger Zelazny Project Amber
  43. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 43 A pattern is a combination of a match predicate that determines if the pattern matches a target, along with a set of pattern variables that are conditionally extracted if the pattern matches the target. Java 16 : Pattern Match for IntanceOf Pattern Matching for Java Gavin Bierman and Brian Goetz, September 2018 https://github.com/openjdk/amber-docs/blob/master/site/design-notes/pattern-matching-for-java.md
  44. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 44 String name = type pattern String = le nom du pattern name = binding variable o = target operand Type Pattern if (o instanceof String name) { // some code }
  45. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 45 Un Record is built on components It has a canonical constructor It is immutable, it cannot extend any class, it is final It has accessors, equals(), hashCode(), toString() Record (JDK 16) public record Car(Color color) {} public record Rectangle(int width, int height) {}
  46. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 46 Record Deconstruction if (o instanceof Rectangle rectangle) { int width = rectangle.width(); int height = rectangle.height(); // do something with width and height }
  47. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 47 Un record pourra être « déconstruit » width et height deviennent des binding variables Record Deconstruction if (o instanceof Rectangle(int width, int height)) { // do something with width and height }
  48. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 48 Three type patterns Three pattern binding variables One target operand Patterns Matching for Switch String formatted = switch(number) { case Integer i -> String.format("int %d", i); case Long l -> String.format("long %d", l); case Double d -> String.format("double %d", d); }
  49. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 49 Deconstruction + Pattern Matching for Switch record Square(int edge) {} record Circle(int radius) {} double area = switch(shape) { case Square(int edge) -> edge* edge; case Circle(int radius) -> Math.PI*radius*radius; default -> ...; }
  50. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 50 Sealed Classes (JDK 17) sealed interface Shape permits Rectangle, Square, Circle { } public final class Rectangle implements Shape {} public record Circle(Point center) implements Shape {} public non-sealed abstract class MoreShapes implements Shape {}
  51. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 51 The hierarchy is « sealed » Sealed Classes (JDK 17) sealed interface Shape permits Rectangle, Square, Circle { } public final class Rectangle implements Shape {} public record Circle(Point center) implements Shape {} public final class Square implements Shape {}
  52. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 52 The default case becomes useless = total switch Pattern Matching for Switch + Sealed Types double area = switch(shape) { case Square(int edge) -> edge* edge; case Circle(int radius) -> Math.PI*radius*radius; // default -> ...; }
  53. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 53 Record Deconstruction (Again) if (o instanceof Rectangle rectangle) { int width = rectangle.width(); int height = rectangle.height(); // do something with width and height }
  54. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 54 A record can be « deconstructed » width et height become binding variables Record Deconstruction (Again) if (o instanceof Rectangle(int width, int height)) { // do something with width and height }
  55. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 55 Array Pattern Matching if (o instanceof String[] array && array.length() >= 2) { // do something with array[0] and array[1] }
  56. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 56 Array Pattern Matching if (o instanceof String[] {String s1, String s2}) { // do something with s1 and s2 }
  57. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 57 Array Pattern Matching if (o instanceof Circle[] {Circle(var r1), Circle(var r3)}) { // do something with r1 and r2 }
  58. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 58 Record Pattern Matching for Switch record Square(int edge) {} record Circle(int radius) {} double area = switch(shape) { case Square(int edge) -> edge* edge; case Circle(int radius) -> Math.PI*radius*radius; default -> ...; }
  59. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 59 You can use var in patterns Syntaxic Sugars if (shape instanceof Circle(var center, var radius)) { // center and radius are binding variables } record Point(int x, int y) {} record Circle(Point center, int radius) implements Shape {}
  60. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 60 You can tell that you do not need a binding variable Syntaxic Sugars if (shape instanceof Circle(var center, _)) { // center and radius are binding variables } record Point(int x, int y) {} record Circle(Point center, int radius) implements Shape {}
  61. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 61 You can nest patterns (nested patterns) Syntaxic Sugars if (shape instanceof Circle(var center, _) && center instanceof Point(int x, int y)) { // center and radius are binding variables } if (shape instanceof Circle(Point(int x, int y), _)) { // center and radius are binding variables }
  62. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 62 The deconstruction uses the canonical constructor of a record What about: - factory methods? - classes that are not records? Deconstruction
  63. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 63 Deconstruction Using Factory Methods interface Shape { static Circle circle(double radius) { return new Circle(radius); } static Square square(double edge) { return new Square(edge); } } record Circle(double radius) {} record Square(double edge) {}
  64. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 64 Then this code becomes possible: Deconstruction Using Factory Methods double area = switch(shape) { case Shape.circle(double radius) -> Math.PI*radius*radius; case Shape.square(double edge) -> edge*edge; }
  65. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 65 What About Your POJOs? public class Point { private int x, y; public Point(int x, int y) { this.x = x; this.y = y; } public deconstructor(int x, int y) { x = this.x; y = this.y; } } Binding variables They are the same! external state description Defensive copy Overloading? Overloading!
  66. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 66 You saw patterns with instanceof and switch Let us see match ! Pattern with Match record Point(int x, int y) {} record Circle(Point center, int radius) implements Shape {} Circle circle = ...; match Circle(var center, var radius) = circle; // center and radius are binding variables
  67. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 67 If shape is in fact a rectangle… You can throw an exception Pattern with Match Shape shape = ...; match Circle(var center, var radius) = shape else throw new IllegalStateException("Not a circle"); // center and radius are binding variables
  68. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 68 If shape is in fact a rectangle … Or define default values Pattern with Match Shape shape = ...; match Circle(Point center, int radius) = shape else { center = new Point(0, 0); // this is called radius = 1d; // an anonymous matcher } // center and radius are binding variables
  69. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 69 You can use match with more than one pattern… … or use nested patterns Pattern with Match Shape shape = ...; match Rectangle(var p1, var p2) = shape, Point(var x0, var y0) = p1, Point(var x1, var y2) = p2;
  70. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 70 You can create maps with factory methods This is an extended form of Pattern Matching where you check the value of a binding variable More Examples if (map instanceof Map.withMapping("name", var name) && map instanceof Map.withMapping("email", var email)) { // name and email are binding variables }
  71. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 71 Pattern combination More Examples if (map instanceof Map.withMapping("name", var name) __AND map instanceof Map.withMapping("email", var email)) { // name and email are binding variables } __AND = pattern combination
  72. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 72 More Examples { "firstName": "John", "lastName": "Smith", "age": 25, "address" : { "street": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": "10021" } } if (json instanceof stringKey("firstName", var firstName) __AND stringKey("lastName", var lastName) __AND intKey("age", var age) __AND objectKey("address", stringKey("stree", var street) __AND stringKey("city", var city) __AND stringKey("state", var state) )) { // firstName, lastName, age, // street, city, state, ... // are binding variables }
  73. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 73 If Java Embraces « Map Literals » Map<String, String> map = { "firstName": "John", "lastName": "Smith", "age": "25" } if (map instanceof { "firstName": var firstName, "lastName": var lastName, "age": Integer.toString(var age) }) { // firstName, lastName, age // are binding variables }
  74. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 74 • Constant Patterns: checks the operand with a constant value • Type Patterns: checks if the operand has the right type, casts it, and creates a binding variable Patterns at a Glance
  75. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 75 • Patterns + Deconstruction: checks the operand type, casts it, bind the component to binding variables • Patterns + Method: uses a factory method or a deconstructor • Patterns + Var: infers the right type, and creates the binding variable • Pattern + _: infers the right type, but does not create the binding variable Patterns at a Glance
  76. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 76 « We don’t want to be the first to include a feature, because every feature we add will never be removed » Brian Goetz, Java Language Architect Everything Takes Time!
  77. 11/2/2021 Copyright © 2021, Oracle and/or its affiliates | 77 Where are we? • Pattern Matching for instanceof • Pattern Matching for Switch • Record and Array Pattern Matching • Match • Literals Patterns at a Glance
Advertisement