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

yanngaelgueheneuc 10 views 189 slides Oct 30, 2025
Slide 1
Slide 1 of 522
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52
Slide 53
53
Slide 54
54
Slide 55
55
Slide 56
56
Slide 57
57
Slide 58
58
Slide 59
59
Slide 60
60
Slide 61
61
Slide 62
62
Slide 63
63
Slide 64
64
Slide 65
65
Slide 66
66
Slide 67
67
Slide 68
68
Slide 69
69
Slide 70
70
Slide 71
71
Slide 72
72
Slide 73
73
Slide 74
74
Slide 75
75
Slide 76
76
Slide 77
77
Slide 78
78
Slide 79
79
Slide 80
80
Slide 81
81
Slide 82
82
Slide 83
83
Slide 84
84
Slide 85
85
Slide 86
86
Slide 87
87
Slide 88
88
Slide 89
89
Slide 90
90
Slide 91
91
Slide 92
92
Slide 93
93
Slide 94
94
Slide 95
95
Slide 96
96
Slide 97
97
Slide 98
98
Slide 99
99
Slide 100
100
Slide 101
101
Slide 102
102
Slide 103
103
Slide 104
104
Slide 105
105
Slide 106
106
Slide 107
107
Slide 108
108
Slide 109
109
Slide 110
110
Slide 111
111
Slide 112
112
Slide 113
113
Slide 114
114
Slide 115
115
Slide 116
116
Slide 117
117
Slide 118
118
Slide 119
119
Slide 120
120
Slide 121
121
Slide 122
122
Slide 123
123
Slide 124
124
Slide 125
125
Slide 126
126
Slide 127
127
Slide 128
128
Slide 129
129
Slide 130
130
Slide 131
131
Slide 132
132
Slide 133
133
Slide 134
134
Slide 135
135
Slide 136
136
Slide 137
137
Slide 138
138
Slide 139
139
Slide 140
140
Slide 141
141
Slide 142
142
Slide 143
143
Slide 144
144
Slide 145
145
Slide 146
146
Slide 147
147
Slide 148
148
Slide 149
149
Slide 150
150
Slide 151
151
Slide 152
152
Slide 153
153
Slide 154
154
Slide 155
155
Slide 156
156
Slide 157
157
Slide 158
158
Slide 159
159
Slide 160
160
Slide 161
161
Slide 162
162
Slide 163
163
Slide 164
164
Slide 165
165
Slide 166
166
Slide 167
167
Slide 168
168
Slide 169
169
Slide 170
170
Slide 171
171
Slide 172
172
Slide 173
173
Slide 174
174
Slide 175
175
Slide 176
176
Slide 177
177
Slide 178
178
Slide 179
179
Slide 180
180
Slide 181
181
Slide 182
182
Slide 183
183
Slide 184
184
Slide 185
185
Slide 186
186
Slide 187
187
Slide 188
188
Slide 189
189
Slide 190
190
Slide 191
191
Slide 192
192
Slide 193
193
Slide 194
194
Slide 195
195
Slide 196
196
Slide 197
197
Slide 198
198
Slide 199
199
Slide 200
200
Slide 201
201
Slide 202
202
Slide 203
203
Slide 204
204
Slide 205
205
Slide 206
206
Slide 207
207
Slide 208
208
Slide 209
209
Slide 210
210
Slide 211
211
Slide 212
212
Slide 213
213
Slide 214
214
Slide 215
215
Slide 216
216
Slide 217
217
Slide 218
218
Slide 219
219
Slide 220
220
Slide 221
221
Slide 222
222
Slide 223
223
Slide 224
224
Slide 225
225
Slide 226
226
Slide 227
227
Slide 228
228
Slide 229
229
Slide 230
230
Slide 231
231
Slide 232
232
Slide 233
233
Slide 234
234
Slide 235
235
Slide 236
236
Slide 237
237
Slide 238
238
Slide 239
239
Slide 240
240
Slide 241
241
Slide 242
242
Slide 243
243
Slide 244
244
Slide 245
245
Slide 246
246
Slide 247
247
Slide 248
248
Slide 249
249
Slide 250
250
Slide 251
251
Slide 252
252
Slide 253
253
Slide 254
254
Slide 255
255
Slide 256
256
Slide 257
257
Slide 258
258
Slide 259
259
Slide 260
260
Slide 261
261
Slide 262
262
Slide 263
263
Slide 264
264
Slide 265
265
Slide 266
266
Slide 267
267
Slide 268
268
Slide 269
269
Slide 270
270
Slide 271
271
Slide 272
272
Slide 273
273
Slide 274
274
Slide 275
275
Slide 276
276
Slide 277
277
Slide 278
278
Slide 279
279
Slide 280
280
Slide 281
281
Slide 282
282
Slide 283
283
Slide 284
284
Slide 285
285
Slide 286
286
Slide 287
287
Slide 288
288
Slide 289
289
Slide 290
290
Slide 291
291
Slide 292
292
Slide 293
293
Slide 294
294
Slide 295
295
Slide 296
296
Slide 297
297
Slide 298
298
Slide 299
299
Slide 300
300
Slide 301
301
Slide 302
302
Slide 303
303
Slide 304
304
Slide 305
305
Slide 306
306
Slide 307
307
Slide 308
308
Slide 309
309
Slide 310
310
Slide 311
311
Slide 312
312
Slide 313
313
Slide 314
314
Slide 315
315
Slide 316
316
Slide 317
317
Slide 318
318
Slide 319
319
Slide 320
320
Slide 321
321
Slide 322
322
Slide 323
323
Slide 324
324
Slide 325
325
Slide 326
326
Slide 327
327
Slide 328
328
Slide 329
329
Slide 330
330
Slide 331
331
Slide 332
332
Slide 333
333
Slide 334
334
Slide 335
335
Slide 336
336
Slide 337
337
Slide 338
338
Slide 339
339
Slide 340
340
Slide 341
341
Slide 342
342
Slide 343
343
Slide 344
344
Slide 345
345
Slide 346
346
Slide 347
347
Slide 348
348
Slide 349
349
Slide 350
350
Slide 351
351
Slide 352
352
Slide 353
353
Slide 354
354
Slide 355
355
Slide 356
356
Slide 357
357
Slide 358
358
Slide 359
359
Slide 360
360
Slide 361
361
Slide 362
362
Slide 363
363
Slide 364
364
Slide 365
365
Slide 366
366
Slide 367
367
Slide 368
368
Slide 369
369
Slide 370
370
Slide 371
371
Slide 372
372
Slide 373
373
Slide 374
374
Slide 375
375
Slide 376
376
Slide 377
377
Slide 378
378
Slide 379
379
Slide 380
380
Slide 381
381
Slide 382
382
Slide 383
383
Slide 384
384
Slide 385
385
Slide 386
386
Slide 387
387
Slide 388
388
Slide 389
389
Slide 390
390
Slide 391
391
Slide 392
392
Slide 393
393
Slide 394
394
Slide 395
395
Slide 396
396
Slide 397
397
Slide 398
398
Slide 399
399
Slide 400
400
Slide 401
401
Slide 402
402
Slide 403
403
Slide 404
404
Slide 405
405
Slide 406
406
Slide 407
407
Slide 408
408
Slide 409
409
Slide 410
410
Slide 411
411
Slide 412
412
Slide 413
413
Slide 414
414
Slide 415
415
Slide 416
416
Slide 417
417
Slide 418
418
Slide 419
419
Slide 420
420
Slide 421
421
Slide 422
422
Slide 423
423
Slide 424
424
Slide 425
425
Slide 426
426
Slide 427
427
Slide 428
428
Slide 429
429
Slide 430
430
Slide 431
431
Slide 432
432
Slide 433
433
Slide 434
434
Slide 435
435
Slide 436
436
Slide 437
437
Slide 438
438
Slide 439
439
Slide 440
440
Slide 441
441
Slide 442
442
Slide 443
443
Slide 444
444
Slide 445
445
Slide 446
446
Slide 447
447
Slide 448
448
Slide 449
449
Slide 450
450
Slide 451
451
Slide 452
452
Slide 453
453
Slide 454
454
Slide 455
455
Slide 456
456
Slide 457
457
Slide 458
458
Slide 459
459
Slide 460
460
Slide 461
461
Slide 462
462
Slide 463
463
Slide 464
464
Slide 465
465
Slide 466
466
Slide 467
467
Slide 468
468
Slide 469
469
Slide 470
470
Slide 471
471
Slide 472
472
Slide 473
473
Slide 474
474
Slide 475
475
Slide 476
476
Slide 477
477
Slide 478
478
Slide 479
479
Slide 480
480
Slide 481
481
Slide 482
482
Slide 483
483
Slide 484
484
Slide 485
485
Slide 486
486
Slide 487
487
Slide 488
488
Slide 489
489
Slide 490
490
Slide 491
491
Slide 492
492
Slide 493
493
Slide 494
494
Slide 495
495
Slide 496
496
Slide 497
497
Slide 498
498
Slide 499
499
Slide 500
500
Slide 501
501
Slide 502
502
Slide 503
503
Slide 504
504
Slide 505
505
Slide 506
506
Slide 507
507
Slide 508
508
Slide 509
509
Slide 510
510
Slide 511
511
Slide 512
512
Slide 513
513
Slide 514
514
Slide 515
515
Slide 516
516
Slide 517
517
Slide 518
518
Slide 519
519
Slide 520
520
Slide 521
521
Slide 522
522

About This Presentation

All new, noteworthy features of Java, from Java 1.7 to Java 25, with discussions and code examples. It includes all the following features, JEP, and JSR: Enums, JSR-292, Strings in switch, try With Resources, Diamond Operator , Vargs in Method Declaration, Binary Integer Literals, Underscores in Num...


Slide Content

Yann-Gaël Guéhéneuc
(/jan/, he/il)
Work licensed under Creative Commons
BY-NC-SA 4.0 International
New Java
[email protected]
Version 0.25
2025/09/16

2/522
Any questions/comments are welcome at
[email protected]
Source code available at
https://github.com/ptidejteam/tutorials-NewJava

3/522
Patrick Naughton
Scott McNealy
Mike SheridanJames Gosling
1991

4/522

5/522
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/522
Process 
JCP: Java Community Process
–Established in 1998
–JSR-387 describes JCP v2.11

7/522
Documents 
JLSs: Java Language Specifications
– What isJava 
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-di fference-or-relation-between-jls-jsr-and-jep

8/522
About the JDK
https://medium.com/@zaam.oussama/java-development-kit-jdk-exploring-its-components-and-functionality-8f6d6c2a0 46c

9/522
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-8f6d6c2a0 46c

10/522
About the JDK
https://medium.com/@zaam.oussama/java-development-kit-jdk-exploring-its-components-and-functionality-8f6d6c2a0 46c

11/522
About the JDK
https://medium.com/@zaam.oussama/java-development-kit-jdk-exploring-its-components-and-functionality-8f6d6c2a0 46c

12/522
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-8f6d6c2a0 46c

13/522
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/522
About the JDK
https://bugs.openjdk.org/secure/attachment/72525/jdk.png

15/522
About the JDK
https://www.infoq.com/news/2025/09/java25-released/

16/522
About the JDK

TL;DR
– LTS doesn’t exist/make
sense for Java itself
• Support is NOT a
software property, BUT a
relation with a vendor
– Java 8, 11, 17, 21, and
25 have “general”
commercial support
• Other vendors may
support other versions?

17/522
About the JDK

TL;DR
– LTS doesn’t exist/make
sense for Java itself
• Support is NOT a
software property, BUT a
relation with a vendor
– Java 8, 11, 17, 21, and
25 have “general”
commercial support
• Other vendors may
support other versions?

18/522
Disclaimer

19/522
Too
Many
Features
Disclaimer
No
Preview
No
Incubator
Or just a few…

20/522
Organisation 
Per release
–With some cross-references

Three categories
–Language
–JVM
–APIs
Misc
+

21/522
In Summary (With Few Examples) 
Language
– Reduce risk of bugs
• trywith resources
– Simplify coding
• switchwith 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

22/522
In Summary (With Few Examples) 
JVM
– APIs
• Tools
• GCs
– Release
• Statically-linked libraries
– Performance
• JIT
– Graal VM
• GCs
– Implementations
– NUMA

23/522
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

24/522
In Summary (With Few Examples) 
Misc.
–Coding
• jshell
• Java files launching
• Instance main method
–Release
• jlink and jpackage
–Performance
• jaotc

25/522
Java 5
Java 6
2004/09/30
2006/12/11

26/522
LANGUAGE (ONLY)

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

28/522
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
);
}

29/522
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()

30/522
Enums EnumSimulated 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();
}
}

31/522
Enums EnumSimulated 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

32/522
Enums EnumSimulated 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

33/522
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
// ...
}

34/522
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

35/522
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
;

36/522
Java 7
2011/07/07 2011/07/07

37/522
LANGUAGE

38/522
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
;
}

39/522
tryWith 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();
}

40/522
Diamond Operator <>
https://www.baeldung.com/java-diamond-operator
List<String>
cars
=
new
ArrayList<String>();
List<String>
cars
=
new
ArrayList<>();
vs.

41/522
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.

42/522
Binary Integer Literals
https://www.geeksforgeeks.org/java-program-to-illustrate-u se-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;

43/522
Underscores in Numeric Literals
int
i
= 12_34_56;
System.
out
.println(
i
);
https://www.geeksforgeeks.org/using-underscore-numeric-lite rals-java/

44/522
Multiple Exception Types 
Multiple exception types

Multiple exceptions rethrown
with improved type checking

45/522
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
);
}
}
// ...

46/522
JVM

47/522
JSR-292: invokedynamic 
invokestatic, for class methods

invokevirtual, for instance methods

invokeinterface, for interface methods

invokespecial, for instance initialisation,
superclass, and private methods

48/522
JSR-292: invokedynamic
Gilad Bracha, 2005

49/522
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'
);

50/522
APIS

51/522
JSR-166: Concurrency Utilities 
Concurrency utilities under JSR 166

java.util.concurrentwants 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-slid es.pdf

52/522
JSR-166: Concurrency Utilities
https://www.uml-diagrams.org/java-7-concurrent-uml-class-d iagram-example.html

53/522
JSR-166: Concurrency Utilities
https://www.uml-diagrams.org/java-7-concurrent-uml-class-d iagram-example.html

54/522
JSR-166: Concurrency Utilities
https://www.uml-diagrams.org/java-7-concurrent-uml-class-d iagram-example.html

55/522
JSR-166: Concurrency Utilities
https://gee.cs.oswego.edu/dl/concurrency-interest/jsr166-slid es.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.

56/522
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-slid es.pdf

57/522
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

58/522
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/

59/522
JSR-166: Concurrency Utilities
https://www.geeksforgeeks.org/atomic-variables-in-java-wit h-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();
}
}

60/522
JSR-203: New File I/O Library 
Extensive File I/O API

Socket channel API

Asynchronous I/O API

61/522
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:\\Documents\\Tutorials\\220926 - New Java"
);
final
String
fileName
=
"Example1FileVisitor.java"
;
final
FileVisitorImpl
visitor
=
new
FileVisitorImpl(
fileName
,
startPath
);
Files.walkFileTree(
startPath
,
visitor
);
}
}

62/522
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
;
}
}

63/522
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:\\Documents\\Tutorials\\220926 - New Java\\ReceivedFile.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_chan nel.htm

64/522
JSR-203: New File I/O Library 
Socket channel API –Server
https://www.tutorialspoint.com/java_nio/java_nio_socket_chan nel.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:\\\\Documents\\\\Tutorials\\\\220926 - New Java\\\\Patterns.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();
}

65/522
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_chan nel.htm

66/522
JSR-203: New File I/O Library 
Asynchronous I/O API
“The asynchronous channel APIs were
introduced into the existing
java.nio.channelspackage […] by
prefixing […] with Asynchronous”

67/522
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)

68/522
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.h tml
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();
// ...

69/522
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

70/522
Java 8
2014/03/18

71/522
LANGUAGE

72/522
default, staticInterface 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());
}

73/522
default, staticInterface 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

74/522
default, staticInterface 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());
}

75/522
default, staticInterface 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());
}

76/522
default, staticInterface 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());

77/522
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

78/522
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!"
));
}

79/522
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!"
));
}

80/522
JSR-335, JEP-126: λExpressions 
Solution
–Simple syntactic sugar
–Set of functionalinterfaces
–Libraries using these interfaces

81/522
JSR-335, JEP-126: λExpressions 
Solution
–Simple syntactic sugar –Set of functionalinterfaces
–Libraries using these interfaces

82/522
JSR-335, JEP-126: λExpressions 
Solution
–Simple syntactic sugar –Set of functionalinterfaces
–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!"
));
}

83/522
JSR-335, JEP-126: λExpressions 
Solution
–Simple syntactic sugar –Set of functionalinterfaces
–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!"
));
}

84/522
JSR-335, JEP-126: λExpressions 
Solution
–Simple syntactic sugar
–Set of functionalinterfaces –Libraries using these interfaces
http://blog.orfjackal.net/2014/07/java-8-functional-int erface-naming-guide.html

85/522
JSR-335, JEP-126: λExpressions 
Solution
–Simple syntactic sugar
–Set of functionalinterfaces –Libraries using these interfaces
http://blog.orfjackal.net/2014/07/java-8-functional-int erface-naming-guide.html

86/522
JSR-335, JEP-126: λExpressions 
Solution
–Simple syntactic sugar
–Set of functionalinterfaces
–Libraries using these interfaces
https://blogs.oracle.com/javamagazine/post/functional-progr amming-in-java-part-1-lists-lambdas-and-method-refere nces

87/522
JSR-335, JEP-126: λExpressions 
Solution
–Simple syntactic sugar
–Set of functionalinterfaces
–Libraries using these interfaces
https://blogs.oracle.com/javamagazine/post/functional-progr amming-in-java-part-1-lists-lambdas-and-method-refere nces 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
);

88/522
JSR-335, JEP-126: λExpressions 
But code duplication!
https://blogs.oracle.com/javamagazine/post/functional-progr amming-
in-java-part-2-lambda-reuse-lexical-scoping-and-closures-a nd-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.

89/522
JSR-335, JEP-126: λExpressions 
But code duplication!
https://blogs.oracle.com/javamagazine/post/functional-progr amming-
in-java-part-2-lambda-reuse-lexical-scoping-and-closures-a nd-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.

90/522
JSR-335, JEP-126: λExpressions 
But code duplication!
https://blogs.oracle.com/javamagazine/post/functional-progr amming-
in-java-part-2-lambda-reuse-lexical-scoping-and-closures-a nd-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.

91/522
JSR-335, JEP-126: λExpressions 
But code duplication!
https://forum.devtalk.com/t/functional-programming-in-ja va-second-
edition-p-35-refactoring-to-narrow-the-scope-code/10544 7
// 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.

92/522
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
);
}
}

93/522
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
);
}
}

94/522
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

95/522
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

96/522
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
);
}
}
}

97/522
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 '@NonNullString'

98/522
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/

99/522
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)"
);
}
}
}

100/522
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/

101/522
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/

102/522
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
);
}
}

103/522
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")

104/522
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
);
}
}

105/522
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

106/522
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
);
}
}

107/522
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")})

108/522
JVM

109/522
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

110/522
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

111/522
APIS

112/522
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

113/522
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
);

114/522
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.*

115/522
MISC

116/522
JEP-153: JavaFX Applications 
Three “types” of programs
–Class files
–JAR files
–JavaFX

Enhance the javacommand-line to launch
JavaFX programs

117/522
Java 9
2017/09/21

118/522
LANGUAGE

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

120/522
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

121/522
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/

122/522
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

123/522
JSR-376: Modularization 
Classpath / JARs Hell

Version conflicts

Large Monolithic JDK

Security Problems
https://www.geeksforgeeks.org/jpms-java-platform-module-system/

124/522
JSR-376: Modularization 
Classpath/ JARs Hell

Version conflicts
–Cf. DLL Hell, no versions, one directory
–One, longlist 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/

125/522
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/

126/522
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/

127/522
JSR-376: Modularization

128/522
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

129/522
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;
}

130/522
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;
}

131/522
JSR-376: Modularization

Declaration of module com.example.foo

Dependencies on
three other modules
– transitive: client
modules also can
access thatmodule
– 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;
}

132/522
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;
}

133/522
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.networkor
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;
}

134/522
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

135/522
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

136/522
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!)

137/522
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

138/522
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
...

139/522
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

140/522
JSR-376: Modularization

Client

Provider
module
ModularizationWithModulesClient1 {
requires
ModularizationWithModulesLibrary1;
}
module
ModularizationWithModulesLibrary1 {
exports
net.ptidej.modularisation.kernel;
exports
net.ptidej.modularisation.kernel.impl;
}

141/522
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

142/522
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

143/522
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

144/522
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;
}

145/522
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();

146/522
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();

147/522
JSR-376: Modularization 
Accessibility
–Observability
–Readability
• requiresvs. requires transitive
–Visibility
• publicvs. “default”
Problem: How to decide what packages and
types are accessible?
Solution: Readability vs. Visibility

148/522
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())

149/522
JSR-376: Modularization
https://www.baeldung.com/java-illegal-reflective-access

Backward compatibility

Automatic module name
–Classpathvs. Module path
–JAR found on the module path

150/522
JSR-376: Modularization
https://medium.com/@dvsingh9/java-modules-a-complete-guide-part-2-340e5b8d26

151/522
JSR-376: Modularization
https://docs.oracle.com/javase%2F9%2Fdocs%2Fapi%2F%2F/overview-summary.html

152/522
JSR-376: Modularization
https://docs.oracle.com/javase%2F9%2Fdocs%2Fapi%2F%2F/java/lang/Module.html

153/522
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
•Modularprograms and libraries
• IoT and other constrained devices
https://www.techtarget.com/searchnetworking/definition/OS Gi

154/522
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-modulari ty/, https://www.infoq.com/articles/java9-osgi-future-mod ularity-
part-2/, https://www.baeldung.com/java-illegal-reflecti ve-access, https://en.wikipedia.org/wiki/OSGi

155/522
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-modulari ty/, https://www.infoq.com/articles/java9-osgi-future-mod ularity-
part-2/, https://www.baeldung.com/java-illegal-reflecti ve-access, https://en.wikipedia.org/wiki/OSGi

156/522
JEP-213: Milling Project Coin 
From Java 7
– Allow @SafeVargson private instance methods
– Allow effectively-finalvariables 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

157/522
JVM

158/522

Nothing to mention, so much
work went into modularisation

159/522
APIS

160/522
Collection Factory Methods 
No nullvalues

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

161/522
Collection Factory Methods 
No nullvalues

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
)

162/522
JavaDB Removal 
JavaDB was a repackaging of Apache Derby
–Relational database
–Open-source
–Entirely in Java
–Embedded JDBC driver

163/522
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) orUTF-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

164/522
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-l ooks-tiny-on-high-dpi-screen-when-it-should-be-scaled-to- normal

165/522
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
));

166/522
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>

167/522
MISC

168/522
JEP-222: jshell

169/522
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 \
net\ptidej\newjava\jlink\HelloWorld.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

170/522
JEP-295: jaotc 
Ahead-of-time compilation
–Compile Java classes to native code
beforelaunching 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

171/522
Java 10
2018/03/20

172/522
LANGUAGE

173/522
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.

174/522
JVM

175/522
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;
// ...

176/522
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/

177/522
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

178/522
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>

179/522
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-in tro-to-nvdimm-n/
-XX:AllocateHeapAt=<path>

180/522
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

181/522
APIS

182/522
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

183/522
MISC

184/522
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
...

185/522
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
...

186/522
JEP-313: Native-Header Generation
Tool Removal

javahfeatures (and more) now in javac
javac HelloWorld.java
javah HelloWorld
javac -h jni -d bin HelloWorld.java
vs.

187/522
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

188/522
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());

189/522
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

190/522
Java 11
2018/09/25

191/522
LANGUAGE

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

193/522
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
);
}
}
}

194/522
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

195/522
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"
));
}
}

196/522
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

197/522
JVM

198/522
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

199/522
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"
);
}
}

200/522
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
;
}
}

201/522
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.

202/522
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

203/522
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

204/522
JEP-309: Dynamic .classConstants 
Dynamic constants, javacvs. 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

205/522
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());

206/522
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

207/522
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

208/522
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
SomExpensiveDatacreated
only once, with first call()

209/522
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

210/522
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

211/522
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

212/522
JEP-331: Low-overhead Heap
Profiling
https://docs.dynatrace.com/docs/platform-modules/application s-and-microservices/profiling-and-optimization/memory-pro filing

213/522
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

214/522
APIS

215/522
JEP-320: Java EE and CORBA
Modules Removal

Since Java 1.2
– OMG CORBA API
– ORB implementation
– CosNaming implementation
– idljcompiler
– Support for IDL and IIOP in rmiccompiler
–No significant interest in CORBA anymore

Since Java 6
– Full Web Services stack
–Now available from third parties

Deprecated in Java 9

216/522
JEP-321: HTTP Client 
Problems with HttpURLConnectionAPI
–Designed for (now dead) protocols (gopher…)
–Designed before HTTP/1.1
–Too abstract
–Hard to use
–Badly documented
–Blocking mode only
–Very hard maintenance

217/522
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

218/522
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());

219/522
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"
}

220/522
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

221/522
JEP-335: Nashorn Deprecation 
Since Java 8
–JEP-174

ECMAScript changes rapidly
–Language
–APIs

Maintenance challenges
–Deprecate Nashorn, its APIs, and
jjs

222/522
MISC

223/522
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-monitorin g
-XX:+UnlockCommercialFeatures
-XX:+FlightRecorder
-XX:StartFlightRecording=duration=200s,filename=flight.jfr

224/522
JEP-328: Flight Recorder
https://www.baeldung.com/java-flight-recorder-monitorin g

225/522
JEP-330: Single-file Source-code
Programs Launching

Lower the (early) learning curve
–But no dependency management
java –cp some.jar HelloWorld.java

226/522
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

227/522
Java 12
2019/03/19

228/522
LANGUAGE

229/522

Nothing to mention?

230/522
JVM

231/522
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-th e-jdks-new-superfast-garbage-collectors
-XX:G1MixedGCCountTarget=<number of mixed garbage collections>

232/522
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>

233/522
APIS

234/522
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-highli ghts-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
);
}
}

235/522
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-highli ghts-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]

236/522
MISC

237/522
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

238/522
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

239/522
JEP-230: Microbenchmark Suite 
Run one java.util.UUIDBenchbenchmark
– 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-Over heads.html
make test TEST=micro:UUIDBench.fromType3Bytes

240/522
JEP-230: Microbenchmark Suite 
Run one java.util.UUIDBenchbenchmark
– 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-Over heads.html
make test TEST=micro:UUIDBench.fromType3Bytes
Benchmark Score Error Units
fromType3Bytes 1.460 ±0.089 ops/us

241/522
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/archit ect-benchmarking.html

242/522
Java 13
2019/09/17 2019/09/17 2019/09/17 2019/09/17

243/522
LANGUAGE

244/522

Nothing to mention?

245/522
JVM

246/522
JEP-351: Unused Memory
Uncommit

ZGC automatically returns heap memory to
the operating system when idle
–Cf. JEP-346
-XX:ZUncommitDelay=<seconds>

247/522
APIS

248/522
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

249/522
MISC

250/522

Nothing to mention?

251/522
Java 14
2020/03/17

252/522
LANGUAGE

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

254/522
-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
)

255/522
-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
)

256/522
JEP-361: switchExpressions
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
;
}

257/522
JVM

258/522
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>

259/522
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

260/522
JEP-363: Concurrent Mark Sweep
GC Removal

Since Java 9
–Deprecated CMS

Reduce maintenance costs
–Replaced by G1
–Two new GCs
• ZGC
• Shenandoah

261/522
APIS

262/522
JEP-352: Non-volatile Mapped Byte
Buffers

FileChannelcan 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
) {
// ...
}

263/522
MISC

264/522
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-recor der-and-jfr-event-streaming-in-java-14
https://github.com/flight-recorder/health-report
java -javaagent:health-report.jar com.example.MyProgram

265/522
JEP-349: JFR Event Streaming 
Example: Health Report
https://blogs.oracle.com/javamagazine/post/java-flight-recor der-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 % |
==============================================================================

266/522
Java 15
2020/09/15

267/522
LANGUAGE

268/522
JEP-371: Hidden Classes 
Classes
– Member classes

Methods
– Inner classes
– Anonymous classes
– Lambda expressions

Encapsulation

Reflection

269/522
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

270/522
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
);
}
}

271/522
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

272/522
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

273/522
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
);

274/522
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!

275/522
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

276/522
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 """

277/522
JEP-378: Text Blocks 
Three quotes
–Followed by white space(s)
–Followedbya new line!
final
String
textBlock
=
"""
Hello
World!"""
;
System.
out
.println(
textBlock
);

278/522
JEP-378: Text Blocks 
Three quotes
–Followed by white space(s)
–Followedbya new line!
final
String
textBlock
=
"""
Hello
World!"""
;
System.
out
.println(
textBlock
);
Hello
World!

279/522
JVM

280/522
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

281/522
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

282/522
APIS

283/522
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

284/522
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 liveobject

Since Java 8
–Optional
–Obsolete
• Security

285/522
MISC

286/522

Nothing to mention?

287/522
Java 16
2021/03/16

288/522
LANGUAGE

289/522
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

290/522
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
);
}

291/522
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
);
}

292/522
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"
);

293/522
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

294/522
JVM

295/522
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

296/522
JEP-376: Concurrent Thread-stack
Processing

ZGC thread-stack processing
–From safepoints to concurrent

Remove GC pauses and scalability issues

Make pauses sub-milliseconds

297/522
APIS

298/522

Nothing to mention?

299/522
MISC

300/522
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-jp ackage-is-production-ready-in-java-16/

301/522
JEP-392: Packaging Tool 
Without JRE

With (some of the) JRE
–Cf. JSR-376
https://jfrog.com/blog/java-artifacts-just-got-better-jp ackage-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

302/522
Java 17
2021/09/14

303/522
LANGUAGE

304/522
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

305/522
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

306/522
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

307/522
JVM

308/522

Nothing to mention?

309/522
APIS

310/522
JEP-356: Enhanced Pseudo-random
Number Generators
https://www.baeldung.com/java-17-random-number-generators

311/522
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(
"%s\t%s\t%s\t%s"
,
factory
.group(),
factory
.name(),
factory
.isJumpable(),
factory
.isSplittable())));
final
RandomGenerator
generator
= RandomGenerator.getDefault();
System.
out
.println(
generator
.nextInt());

312/522
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

313/522
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

314/522
MISC

315/522

Nothing to mention?

316/522
Java 18
2022/03/22

317/522
LANGUAGE

318/522
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

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

320/522
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

321/522
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/

322/522
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

323/522
JVM

324/522

Nothing to mention?

325/522
APIS

326/522
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

327/522
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/

328/522
JEP-408: Simple Web Server
final
InetSocketAddress
address
=
new
InetSocketAddress(8080);
final
Path
path1
= Path.of(
"D:\\Documents\\Tutorials\\220926 - New Java"
);
final
HttpServer
server
= SimpleFileServer.createFileServer(
address
,
path1
,
SimpleFileServer.OutputLevel.
VERBOSE
);
final
Path
path2
= Path.of(
"D:\\Documents\\Tutorials\\220926 - New Java\\Workspace"
);
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

329/522
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-m ethod-handles

330/522
JEP-416: Reflection with
Method Handles

Method handles ≈ Reflection API
https://blogs.oracle.com/javamagazine/post/java-reflection-m ethod-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));
}

331/522
JEP-416: Reflection with
Method Handles

Method handles ≈ Reflection API
https://blogs.oracle.com/javamagazine/post/java-reflection-m ethod-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

332/522
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-m ethod-handles
public final native @
PolymorphicSignature
Object invoke(Object...)
throws
Throwable;

333/522
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-m ethod-handles
Djdk.reflect.useDirectMethodHandle=false

334/522
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
• hostsfile 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
);
}

335/522
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
• hostsfile 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
ServiceLoaderwith default object

336/522
MISC

337/522

Nothing to mention?

338/522
Java 19
2022/09/20

339/522

Only previews or incubator

340/522
Java 20
2023/03/21

341/522

Only previews or incubator

342/522
Java 21
2023/09/19

343/522
LANGUAGE

344/522
JEP-440: Record Patterns 
Since Java 16
– instanceof
pattern matching
–Records
–Cf. JEP-394, JEP-395

Record patterns for record values

345/522
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
);
}
}
}

346/522
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

347/522
JEP-441: switchPattern 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?"
);
}
}

348/522
JEP-441: switchPattern 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

349/522
JVM

350/522
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

351/522
APIS

352/522
JEP-431: Sequenced Collections 
Inconsistencies in the collections
–First, last elements
–Reverse order
https://www.baeldung.com/java-21-sequenced-collections
Last Element First Elementlist.get(list.size() – 1) list.get(0) List
deque.getLast() deque.getFirst() Deque
sortedSet.last() sortedSet.first() SortedSet
Missing linkedHS.iterator().next() LinkedHashSet

353/522
JEP-431: Sequenced Collections
https://www.baeldung.com/java-21-sequenced-collections

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

355/522
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)

356/522
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)

357/522
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

358/522
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();

359/522
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

360/522
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

361/522
MISC

362/522
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!"
);
}
}

363/522
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!"
);
}

364/522
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

365/522
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

366/522
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

367/522
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?

368/522
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 javac22 to compile

369/522
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 d oes not have
main method in the form of void main() or void main (String[] args)

370/522
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 d oes not have
main method in the form of void main() or void main (String[] args)
Autogenerated

371/522
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 d oes not have
main method in the form of void main() or void main (String[] args)
Autogenerated
Known by the JVM

372/522
Java 22
2024/03/19

373/522
LANGUAGE

374/522
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
);

375/522
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 ois not used

376/522
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 ois not used

377/522
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 ois not used
Unnamed variable

378/522
JVM

379/522
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

380/522
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/

381/522
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
;
}

382/522
APIS

383/522

Nothing to mention?

384/522
MISC

385/522
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

386/522
Java 23
2024/09/18

387/522
Disclaimer 
Lots of preview/incubating features…
Some still worth mentioning!
(With titles in italic)

388/522
LANGUAGE

389/522
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"
);
}

390/522
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

391/522
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
));
}
}

392/522
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
);
...

393/522
JVM

394/522
JEP-474: ZGC: Generational Mode
by Default

What can I say?

395/522
APIS

396/522
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_();
})));

397/522
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.”

398/522
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;
}
}

399/522
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/522
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;
}

401/522
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;
}

402/522
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;
}

403/522
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
);
...

404/522
MISC

405/522
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
);
}
...

406/522
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();

407/522
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?

408/522
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!"
);
}
}

409/522
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!"
);
}
}

410/522
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!"
);
}

411/522
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!"
);
}

412/522
Java 24 2025/03/18

413/522
LANGUAGE

414/522
Language 
Some preview features…
Some still worth mentioning!

415/522
Language 
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

416/522
JVM

417/522
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%

418/522
JEP-475: Late Barrier Expansion for G1

419/522
JEP-475: Late Barrier Expansion for G1

420/522
JEP-490: ZGC: Remove the Non-
Generational Mode

Remove the non-generational mode

421/522
JEP-490: ZGC: Remove the Non-
Generational Mode

Remove the non-generational mode

What can I say?

422/522
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

423/522
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...

424/522
JEP-483: Ahead-of-Time Class
Loading and Linking

Creates two new files
–An AOT file
• Very large, binary file
• Classes are available instantlyfrom 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.0M9.0M 9.0M
Mar 19 22:10 app.aot
-rw-r--r-- 1 yann None
42K42K42K 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/

425/522
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%)

426/522
JEP-491: Synchronize Virtual
Threads without Pinning

Virtual threads

Platform threads

Arrange “for virtual threads that block in
[synchronizedmethods and blocks] to
release their underlying platform threads”

427/522
APIS

428/522
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

429/522
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_();
})));

430/522
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

431/522
JEP-485: Stream Gatherers
https://www.oracle.com/technical-resources/articles/java/ma14 -java-se-8-streams.html

432/522
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
);
}

433/522
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]

434/522
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/ja va-util-stream/stream-cheat-sheet.html

435/522
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
);
}
}

436/522
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()

437/522
JEP-485: Stream Gatherers 
In particular
– distinct()
uses
equals()
–E.g.,
String
content

What if we want Stringlength?
@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()

438/522
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();

439/522
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();

440/522
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();

441/522
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!

442/522
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…

443/522
JEP-485: Stream Gatherers 
The optional initialiserfunction provides an
object that maintains private state

The integratorfunction integrates a new
element from the input stream

The optional combinerfunction can evaluate
the gatherer in parallel for parallel streams

The optional finisher function is called when
there are no more input elements

444/522
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

445/522
JEP-496 and JEP-497
https://www.wsj.com/articles/d-wave-claims-quantum-supremacy-beating-traditional-computers-155ca634

446/522
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

447/522
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

448/522
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());

449/522
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)

450/522
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

451/522
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

452/522
MISC

453/522
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.”

454/522
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

455/522
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
;
}

456/522
JEP-472: Prepare to Restrict the Use
of JNI
2.
Byte buffers starting at address 0
return
(
*
env)
->
NewDirectByteBuffer
(env,
0
,
10
);

457/522
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);

458/522
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
);

459/522
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-gcl ocker/

460/522
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”

461/522
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

462/522
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.”

463/522
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

464/522
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

465/522
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

466/522
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

467/522
JEP-493: Linking Run-Time Images
without JMODs

“Reduce the size of the JDK by […] 25% by
enabling the jlinktool 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

468/522
Java 25 2025/09/16

469/522
LANGUAGE

470/522
JEP-511: Module Import Declarations

471/522
JEP-511: Module Import Declarations
package
net.ptidej.newjava.moduleimports;
import
net.ptidej.newjava.moduleimports.p1.X1;
public class
A {
public static void
main(
final
String[]
args
) {
final
X1
x1
=
null
;
System.
out
.println(
x1
);
}
}

472/522
JEP-511: Module Import Declarations
package
net.ptidej.newjava.moduleimports;
import
net.ptidej.newjava.moduleimports.p1.X1;
public class
A {
public static void
main(
final
String[]
args
) {
final
X1
x1
=
null
;
System.
out
.println(
x1
);
}
}
package
net.ptidej.newjava.moduleimports;
// import net.ptidej.newjava.moduleimports.p1.X1;
// import net.ptidej.newjava.moduleimports.p1.X2;
// import net.ptidej.newjava.moduleimports.p1.X3;
import module
M1;
public class
B {
public static void
main(
final
String[]
args
) {
final
X1
x1
=
null
;
System.
out
.println(
x1
);
final
X2
x2
=
null
;
System.
out
.println(
x2
);
final
X3
x3
=
null
;
System.
out
.println(
x3
);
}
}

473/522
JEP-511: Module Import Declarations 
Rules for resolving ambiguous imports

Possibility to coalesce import declarations

Suggestion of grouping import declarations

474/522
JEP-512: Compact Source Files and
Instance Main Methods

Used to have too much code, too many
concepts, and too many constructs
void
main() {
final
String
name
= IO.readln(
"Please enter your name: "
);
IO.print(
"Pleased to meet you, "
);
IO.println(
name
);

final
List<String>
characters
= List.of(
"Rick Deckard"
,
"Roy
Batty"
,
"Pris"
,
"Zhora"
,
"Gaff"
,
"Eldon Tyrell"
,
"J.F.
Sebastian"
,
"Leon Kowalski"
);
for
(
var

c
:
characters
) {
IO.println(
c
+
": "
+
c
.length());
}
}

475/522
JEP-513: Flexible Constructor Bodies 
New model for constructor bodies
class
Employee
extends
Person {
private final
String
officeID
;
Employee(
int
age
, String
officeID
) {
if
(
age
< 18 ||
age
> 67) {
// Now fails fast! throw new
IllegalArgumentException(
"..."
);
}
this
.
officeID
=
officeID
;
// Initialised before superclass
super
(
age
);
}
}

476/522
JEP-513: Flexible Constructor Bodies Before
D
--> C
--> B
--> A
--> Object constructor
--> A constructor
--> B constructor
--> C constructor
D constructor
class
Object {
Object() {
// Object constructor body
}
}
class
A
extends
Object {
A() {
super
();
// A constructor
}
}
class
B
extends
A { ... }
class
C
extends
B { ... }
public class
D
extends
C {
D() {
super
();
// D constructor
}
}

477/522
JEP-513: Flexible Constructor Bodies Now
D prologue
--> C prologue
--> B prologue
--> A prologue
--> Object constructor
--> A epilogue
--> B epilogue
--> C epilogue
D epilogue
class
Object {
Object() {
// Object constructor
}
}
class
A
extends
Object {
A() {
// A prologue super
();
// A epilogue
}
}
class
B
extends
A { ... }
class
C
extends
B { ... }
public class
D
extends
C {
D() {
// D prologue super
();
// D epilogue
}
}

478/522
JEP-513: Flexible Constructor Bodies X() {
System.
out
.print(
this
);
// Error:
refers to the current instance
var
x
=
this
.
i
;
// Error:
refers to field of this instance
this
.hashCode();
// Error:
refers to method of this instance
var
y
=
i
;
// Error: refers to field
of this instance
hashCode();
// Error: refers to
method of this instance
i
= 42;
// OK, uninitialized field
s
=
"goodbye"
;
// Error: assignment
to an initialised field
super
();
}
class
Y {
int
i
;
void
m() {
// ...
}
}
class
Z
extends
Y {
Z() {
var
x
=
super
.
i
;
// Error
super
.m();
// Error
super
();
}
}

479/522
JVM

480/522
JEP-519: Compact Object Headers 
Introduced by JEP-450 in JDK 24

Showed stability and performance
–SPECjbb2015
• Garbage collection: 15% less
• Heap space: 22% less
• CPU time: 8% less
java
----XX:+XX:+XX:+ XX:+UnlockExperimentalVMOptions UnlockExperimentalVMOptions UnlockExperimentalVMOptions UnlockExperimentalVMOptions
-XX:+UseCompactObjectHeaders ...

481/522
JEP-521: Generational Shenandoah 
Introduced byJEP-404 in JDK 24

Showed stability and performance
–DaCapo, SPECjbb2015, SPECjvm2008, and
Heapothesys
–Real-world workloads
java -XX:+UseShenandoahGC
----XX:+XX:+XX:+ XX:+UnlockExperimentalVMOptions UnlockExperimentalVMOptions UnlockExperimentalVMOptions UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational ...

482/522
(Note on Garbage Collectors)

JDK17 G1 GC reduces
20% time on GC
– High RPS service 
JDK21 + ZGC is
Netflix’s general GC
– No stop-the-world
– Maximum GC pause
time is close to zero

483/522
(Note on Garbage Collectors)

JDK17 G1 GC reduces
20% time on GC
– High RPS service 
JDK21 + ZGC is
Netflix’s general GC
– No stop-the-world
– Maximum GC pause
time is close to zero

484/522
APIS

485/522
JEP-502: Stable Values 
Problem, solution
–Field initialisation
• Without final, too unconstrained
• With final, too constrained
–Deferred immutability
• Multi-threaded programs

486/522
JEP-502: Stable Values 
Objectives
– “Improve the startup of Java applications by breaking up
the monolithic initialization of application state.
– Decouple the creation of stable values from their
initialization, without significant performance penalti es.
– Guarantee that stable values are initialized at most on ce,
even in multi-threaded programs.
– Enable user code to safely enjoy constant-folding
optimizations previously available only to JDK -internal
code.”

487/522
JEP-502: Stable Values 
Objectives
– “Improve the startup of Java applications by breaking up
the monolithic initialization of application state.
– Decouple the creation of stable values from their
initialization, without significant performance penalti es.
–Guarantee that stable values are initialized at most
once, even in multi-threaded programs.
– Enable user code to safely enjoy
constant-folding
optimizations
previously available only to JDK-internal
code.”

488/522
JEP-502: Stable Values 
Objectives
Concurrent
Updates?
Constant
Folding?
Update
Location
Update
Count
No Yes Constructor or
staticinitialiser
1 finalfield
Yes, by winner Yes, after update Anywhere [0, 1] StableValue
No No Anywhere [0, +∞] Non-finalfield

489/522
JEP-502: Stable Values 
Example
public class
Main<E
extends
Comparable<E>> {
// OLD:
// private StableValue<ISort> sort = null;
// NEW:
private final
StableValue<ISort<E>>
sort
= StableValue.of();
ISort<E> getSortAlgorithm() {
return this
.
sort
.orElseSet(() ->
new
InsertionSort());
}
public static void
main(
final
String[]
args
) {
final
Main<String>
main
=
new
Main<>();
System.
out
.println(
main
.getSortAlgorithm());
}
}

490/522
JEP-502: Stable Values 
Example
>java -version openjdk version "25" 2025-09-16
OpenJDK Runtime Environment (build 25+36-3489)
OpenJDK 64-Bit Server VM (build 25+36-3489, mixed mode, sharing)

491/522
JEP-502: Stable Values 
Example
>javac -source 25 --enable-preview -d bin
src\ca\concordia\soen6461\singleton\stablevalue\*.j ava
>java --enable-preview -cp bin ca.concordia.soen646 1.singleton.stablevalue.Main >java -version openjdk version "25" 2025-09-16
OpenJDK Runtime Environment (build 25+36-3489)
OpenJDK 64-Bit Server VM (build 25+36-3489, mixed mode, sharing)
ca.concordia.soen6461.singleton.stablevalue.Inserti onSort@14dad5dc

492/522
JEP-502: Stable Values 
Implementation
public
T orElseSet(Supplier<?
extends
T>
supplier
) {
Objects.requireNonNull(
supplier
);
final
Object
t
= wrappedContentsAcquire();
return
(
t
==
null
) ? orElseSetSlowPath(
supplier
) : unwrap(
t
);
}
private
T orElseSetSlowPath(Supplier<?
extends
T>
supplier
) {
preventReentry();
synchronized
(
this
) {
final
Object
t
= contents;
// Plain semantics suffice here
if
(
t
==
null
) {
final
T
newValue
=
supplier
.get();
// The mutex is not reentrant so we know newValue should be returned wrapAndSet(
newValue
);
return
newValue
;
}
return
unwrap(
t
);
}
}
private boolean
wrapAndSet(T
newValue
) {
assert
Thread.holdsLock(
this
);
// We know we hold the monitor here so plain semantic is enough if
(contents ==
null
) {
UNSAFE.putReferenceRelease(
this
, CONTENTS_OFFSET, wrap(
newValue
));
return true
;
}
return false
;
}
https://github.com/openjdk/jdk/blob/c6c451ac392cdb54
5ab43dd46918eca6c47cc5f0/src/java.base/share/class
es/jdk/internal/lang/stable/StableValueImpl.java#L127

493/522
JEP-502: Stable Values 
Implementation
public
T orElseSet(Supplier<?
extends
T>
supplier
) {
Objects.requireNonNull(
supplier
);
final
Object
t
= wrappedContentsAcquire();
return
(
t
==
null
) ? orElseSetSlowPath(
supplier
) : unwrap(
t
);
}
private
T orElseSetSlowPath(Supplier<?
extends
T>
supplier
) {
preventReentry();
synchronized
(
this
) {
final
Object
t
= contents;
// Plain semantics suffice here
if
(
t
==
null
) {
final
T
newValue
=
supplier
.get();
// The mutex is not reentrant so we know newValue should be returned wrapAndSet(
newValue
);
return
newValue
;
}
return
unwrap(
t
);
}
}
private boolean
wrapAndSet(T
newValue
) {
assert
Thread.holdsLock(
this
);
// We know we hold the monitor here so plain semantic is enough if
(contents ==
null
) {
UNSAFE.putReferenceRelease(
this
, CONTENTS_OFFSET, wrap(
newValue
));
return true
;
}
return false
;
}
https://github.com/openjdk/jdk/blob/c6c451ac392cdb54
5ab43dd46918eca6c47cc5f0/src/java.base/share/class
es/jdk/internal/lang/stable/StableValueImpl.java#L127
synchronized block,
with double-locking

494/522
JEP-502: Stable Values 
Implementation
public
T orElseSet(Supplier<?
extends
T>
supplier
) {
Objects.requireNonNull(
supplier
);
final
Object
t
= wrappedContentsAcquire();
return
(
t
==
null
) ? orElseSetSlowPath(
supplier
) : unwrap(
t
);
}
private
T orElseSetSlowPath(Supplier<?
extends
T>
supplier
) {
preventReentry();
synchronized
(
this
) {
final
Object
t
= contents;
// Plain semantics suffice here
if
(
t
==
null
) {
final
T
newValue
=
supplier
.get();
// The mutex is not reentrant so we know newValue should be returned wrapAndSet(
newValue
);
return
newValue
;
}
return
unwrap(
t
);
}
}
private boolean
wrapAndSet(T
newValue
) {
assert
Thread.holdsLock(
this
);
// We know we hold the monitor here so plain semantic is enough if
(contents ==
null
) {
UNSAFE.putReferenceRelease(
this
, CONTENTS_OFFSET, wrap(
newValue
));
return true
;
}
return false
;
}
Use of a pointer!?
https://github.com/openjdk/jdk/blob/c6c451ac392cdb54
5ab43dd46918eca6c47cc5f0/src/java.base/share/class
es/jdk/internal/lang/stable/StableValueImpl.java#L127
synchronizedblock,
with double-locking

495/522
JEP-502: Stable Values 
Implementation
public
T orElseSet(Supplier<?
extends
T>
supplier
) {
Objects.requireNonNull(
supplier
);
final
Object
t
= wrappedContentsAcquire();
return
(
t
==
null
) ? orElseSetSlowPath(
supplier
) : unwrap(
t
);
}
private
T orElseSetSlowPath(Supplier<?
extends
T>
supplier
) {
preventReentry();
synchronized
(
this
) {
final
Object
t
= contents;
// Plain semantics suffice here
if
(
t
==
null
) {
final
T
newValue
=
supplier
.get();
// The mutex is not reentrant so we know newValue should be returned wrapAndSet(
newValue
);
return
newValue
;
}
return
unwrap(
t
);
}
}
private boolean
wrapAndSet(T
newValue
) {
assert
Thread.holdsLock(
this
);
// We know we hold the monitor here so plain semantic is enough if
(contents ==
null
) {
UNSAFE.putReferenceRelease(
this
, CONTENTS_OFFSET, wrap(
newValue
));
return true
;
}
return false
;
}
Use of a pointer!?
https://github.com/openjdk/jdk/blob/c6c451ac392cdb54
5ab43dd46918eca6c47cc5f0/src/java.base/share/class
es/jdk/internal/lang/stable/StableValueImpl.java#L127
synchronizedblock,
with double-locking
putReferenceRelease()
→ putReferenceVolatile()
Stores a reference value in a variable,
with volatile store semantics

496/522
JEP-505: Structured Concurrency
Unstructured concurrency
vs.
Code structure reflects task structure

497/522
JEP-505: Structured Concurrency No concurrency

Response handle()
throws
... {
final
String
theUser
=
this
.findUser();
final int
theOrder
=
this
.fetchOrder();
return new
Response(
theUser
,
theOrder
);
}

498/522
JEP-505: Structured Concurrency No concurrency
ExecutorService Response handle()
throws
... {
final
String
theUser
=
this
.findUser();
final int
theOrder
=
this
.fetchOrder();
return new
Response(
theUser
,
theOrder
);
}
Response handle()
throws
... {
final
Future<String>
user
=
this
.
executor
.submit(() -> findUser());
final
Future<Integer>
order
=
this
.
executor
.submit(() -> fetchOrder());
final
String
theUser
=
user
.get();
// Join findUser,
final int
theOrder
=
order
.get();
// Join fetchOrder
return new
Response(
theUser
,
theOrder
);
}

499/522
JEP-505: Structured Concurrency No concurrency
ExecutorService Response handle()
throws
... {
final
String
theUser
=
this
.findUser();
final

int

theOrder
=
this
.fetchOrder();
return

new
Response(
theUser
,
theOrder
);
}
Response handle()
throws
... {
final
Future<String>
user
=
this
.
executor
.submit(() -> findUser());
final
Future<Integer>
order
=
this
.
executor
.submit(() -> fetchOrder());
final
String
theUser
=
user
.get();
// Join findUser,
final int
theOrder
=
order
.get();
// Join fetchOrder
return new
Response(
theUser
,
theOrder
);
}
May be interrupted, but
not the two subtasks

500/522
JEP-505: Structured Concurrency No concurrency
ExecutorService Response handle()
throws
... {
final
String
theUser
=
this
.findUser();
final int
theOrder
=
this
.fetchOrder();
return new
Response(
theUser
,
theOrder
);
}
Response handle()
throws
... {
final
Future<String>
user
=
this
.
executor
.submit(() -> findUser());
final
Future<Integer>
order
=
this
.
executor
.submit(() -> fetchOrder());
final
String
theUser
=
user
.get();
// Join findUser,
final

int

theOrder
=
order
.get();
// Join fetchOrder
return

new
Response(
theUser
,
theOrder
);
}
May be interrupted, but
not the two subtasks
May throw an exception, but fetchOrder()will
continue, and vice versa

501/522
JEP-505: Structured Concurrency 
“[O]ur program is logically structured with
task-subtask relationships, but these
relationships exist only in our minds.”
– java.util.concurrent.ForkJoinPool
designed
for compute-intensive tasks rather than I/O tasks

502/522
JEP-505: Structured Concurrency 
Two ideas
–Execution flow through a block of code with well-
defined entry and exit points
–Operation lifetimes nested in a way that mirrors
their syntactic nesting in the code

Very important with virtual threads

503/522
JEP-505: Structured Concurrency @PreviewFeature
(feature =
PreviewFeature
.Feature.
STRUCTURED_CONCURRENCY
)
public sealed interface
StructuredTaskScope<T, R>
extends
AutoCloseable
permits
StructuredTaskScopeImpl { ... }
public class
Version3
extends
AbstractOrder {
Response handle()
throws
InterruptedException {
try
(
final var
scope
= StructuredTaskScope.open()) {
final
Subtask<String>
user
=
scope
.fork(() -> findUser());
final
Subtask<Integer>
order
=
scope
.fork(() -> fetchOrder());
scope
.join();
// Join subtasks, propagating exceptions
final
String
theUser
=
user
.get();
final int
theOrder
=
order
.get();
return new
Response(
theUser
,
theOrder
);
}
}
}

504/522
JEP-505: Structured Concurrency @PreviewFeature
(feature =
PreviewFeature
.Feature.
STRUCTURED_CONCURRENCY
)
public sealed interface
StructuredTaskScope<T, R>
extends
AutoCloseable
permits
StructuredTaskScopeImpl { ... }
public class
Version3
extends
AbstractOrder {
Response handle()
throws
InterruptedException {
try
(
final var
scope
= StructuredTaskScope.open()) {
final
Subtask<String>
user
=
scope
.fork(() -> findUser());
final
Subtask<Integer>
order
=
scope
.fork(() -> fetchOrder());
scope
.join();
// Join subtasks, propagating exceptions
final
String
theUser
=
user
.get();
final int
theOrder
=
order
.get();
return new
Response(
theUser
,
theOrder
);
}
}
}
Use of sealed/permit
,
AutoClosable!

505/522
JEP-505: Structured Concurrency @PreviewFeature
(feature =
PreviewFeature
.Feature.
STRUCTURED_CONCURRENCY
)
public sealed interface
StructuredTaskScope<T, R>
extends
AutoCloseable
permits
StructuredTaskScopeImpl { ... }
public class
Version3
extends
AbstractOrder {
Response handle()
throws
InterruptedException {
try
(
final var
scope
= StructuredTaskScope.open()) {
final
Subtask<String>
user
=
scope
.fork(() -> findUser());
final
Subtask<Integer>
order
=
scope
.fork(() -> fetchOrder());
scope
.join();
// Join subtasks, propagating exceptions
final
String
theUser
=
user
.get();
final int
theOrder
=
order
.get();
return new
Response(
theUser
,
theOrder
);
}
}
}
Use of sealed/permit
,
AutoClosable!
Error handling with short-circuit
Cancellation propagation
Clarity, ScopedValuebindings
Observability (thread dump)

506/522
Response handle() {
try
(
final var
scope
= StructuredTaskScope.open()) {
final
Subtask<String>
user
=
scope
.fork(() -> findUser());
final
Subtask<Integer>
order
=
scope
.fork(() -> fetchOrder());
scope
.join();
// Join subtasks, propagating exceptions
final
String
theUser
=
user
.get();
final int
theOrder
=
order
.get();
return new
Response(
theUser
,
theOrder
);
}
catch
(
final
StructuredTaskScope.FailedException
| InterruptedException
e
) {
final
Throwable
cause
=
e
.getCause();
switch
(
cause
) {
case
IOException
ioe
-> System.
out
.println(
ioe
);
default
-> System.
out
.println(
cause
);
}
}
...
}

507/522
JEP-506: 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
);
...

508/522
MISC

509/522
JEP-503: Remove the 32-bit x86 Port 
Deprecated (removal) by JEP-501 in JDK 24
–“There is no pressing industry need for 32 -bit
x86 with modern JDKs”
–“There is enough margin for backport safety with
releases that still support 32 -bit x86”
–“The maintenance of other 32-bit ports is not
significantly affected”
–“Fallback options can be tested separately”

510/522
JEP-510: Key Derivation Function API 
“[C]ryptographic algorithms for deriving
additional keys from a secret key, other data”
–“Enable applications to use KDF algorithms”
–...
–“Enable a refactoring of the TLS 1.3 and DHKEM
implementations in the JDK to use the KDF API
rather than an internal HKDF implementation.”

511/522
JEP-514: Ahead-of-Time Command-
line Ergonomics

Introduced by JEP-483 in JDK 24
$ 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 app.jar com.example.App ...
$ 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
$ java
----XX:AOTCache=app.aot XX:AOTCache=app.aot XX:AOTCache=app.aot XX:AOTCache=app.aot -cp app.jar com.example.App ...

512/522
JEP-514: Ahead-of-Time Command-
line Ergonomics

Introduced by JEP-483 in JDK 24
$ 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 app.jar com.example.App ...
$ 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
$ java
----XX:AOTCache=app.aot XX:AOTCache=app.aot XX:AOTCache=app.aot XX:AOTCache=app.aot -cp app.jar com.example.App ...
$ java
----XX:AOTCacheOutput=app.aot XX:AOTCacheOutput=app.aot XX:AOTCacheOutput=app.aot XX:AOTCacheOutput=app.aot -cp app.jar com.example.App ...
$ java
----XX:AOTCache=app.aot XX:AOTCache=app.aot XX:AOTCache=app.aot XX:AOTCache=app.aot -cp app.jar com.example.App ...

513/522
JEP-515: Ahead-of-Time Method
Profiling

Introduced by JEP-483
in JDK 24
– Classes in AOT cache
–Now
, also method profiles
• Does not prevent profiling
during normal runs
– Example
• Almost 900 JDK classes (!)
• 90 ms without profiles
• 73 ms with profiles
– 19% faster
package
net.ptidej.newjava.aotmethodprofiles;
import
java.util.List;
import
java.util.stream.Collectors;
public class
Example {
static
String greeting(
final int
n
) {
var
words
=
List.of(
"Hello"
,
""
+
n
,
"world!"
);
return
words
.stream().filter(
w
-> !
w
.contains(
"0"
))
.collect(Collectors.joining(
", "
));
}
public static void
main(
final
String...
a
) {
for
(
int
i
= 0;
i
< 100_000;
i
++)
Example.greeting(
i
);
System.
out
.println(Example.greeting(0));
}
}

514/522
JEP-518: JFR Cooperative Sampling Before 
JFR samples the stacks of
threads asynchronously 
Suspends threads, parses
their stacks outside of
safepoints
– Stack-parsing heuristics are
inefficient and could crash
the JVM
Now

Records the target thread
counter and stack pointer
in a sample request
– Internal thread-local queue

Safepoint handling code
inspects the queue and
handles sample requests

Not when the target thread
is running native code

515/522
JEP-520: JFR Method Timing, Tracing 
Context
–During development
• Java Microbenchmark Harness
• Java Debug Interface
–During testing, production
• Temporary log statements or JFR events
• Sample-based profilers
• Java agents, such as JProfiler

516/522
JEP-520: JFR Method Timing, Tracing 
Infrastructure for method timing and tracing
via bytecode instrumentation
–Config. files
default.jfc
and
profile.jfc
–New options
method-timing
and
method-trace
• Number of invocations and average execution time
• Stack traces for methods

517/522
JEP-520: JFR Method Timing, Tracing 
Infrastructure for method timing and tracing
via bytecode instrumentation
$ java -XX:StartFlightRecording:jdk.MethodTrace#filter=java.util.HashMap::resize jdk.MethodTrace#filter=java.util.HashMap::resize jdk.MethodTrace#filter=java.util.HashMap::resize jdk.MethodTrace#filter=java.util.HashMap::resize,filename=recording.jfr ...
$ jfr print --events jdk.MethodTrace --stack-depth 20 recording.jfr
jdk.MethodTrace {
startTime = 00:39:26.379 (2025-03-05)
duration = 0.00113 ms
method = java.util.HashMap.resize()
eventThread = "main" (javaThreadId = 3)
stackTrace = [
java.util.HashMap.putVal(int, Object, Object, boolean, boolean) line: 636
java.util.HashMap.put(Object, Object) line: 619
sun.awt.AppContext.put(Object, Object) line: 598
sun.awt.AppContext.<init>(ThreadGroup) line: 240
sun.awt.SunToolkit.createNewAppContext(ThreadGroup) line: 282
sun.awt.AppContext.initMainAppContext() line: 260
sun.awt.AppContext.getAppContext() line: 295
sun.awt.SunToolkit.getSystemEventQueueImplPP() line: 1024
sun.awt.SunToolkit.getSystemEventQueueImpl() line: 1019
java.awt.Toolkit.getEventQueue() line: 1375
java.awt.EventQueue.invokeLater(Runnable) line: 1257
javax.swing.SwingUtilities.invokeLater(Runnable) line: 1415
java2d.J2Ddemo.main(String[]) line: 674
]
}

518/522
JEP-520: JFR Method Timing, Tracing 
Infrastructure for method timing and tracing
via bytecode instrumentation
–Custom annotations
$ java ----XX:StartFlightRecording:method XX:StartFlightRecording:method XX:StartFlightRecording:method XX:StartFlightRecording:[email protected] [email protected] [email protected] [email protected] ...
@Retention
(RetentionPolicy.
RUNTIME
)
@Target
({ ElementType.
TYPE
, ElementType.
METHOD
})
public

@interface

Debug
{
}

519/522
JEP-520: JFR Method Timing, Tracing 
Infrastructure
for method
timing and
tracing via
bytecode
instrumentation
– Remote
configuration
// Establish non-secure connection to remote host var
url
=
"service:jmx:rmi:///jndi/rmi://example.com:7091/jmxrmi"
;
var
jmxURL
=
new
JMXServiceURL(
url
);
try
(
var
conn
= JMXConnectorFactory.connect(
jmxURL
)) {
try
(
var
r
=
new
RemoteRecordingStream(
conn
.getMBeanServerConnection())) {
// Create map for settings var
settings
=
new
HashMap<String, String>();
// Trace methods settings
.put(
"jdk.MethodTrace#enabled"
,
"true"
);
settings
.put(
"jdk.MethodTrace#stackTrace"
,
"true"
);
settings
.put(
"jdk.MethodTrace#threshold"
,
"1 ms"
);
settings
.put(
"jdk.MethodTrace#filter"
,
"com.foo.Bar"
);
// Subscribe to trace events r.onEvent(
"jdk.MethodTrace"
, event -> ...);
// Measure execution time settings
.put(
"jdk.MethodTiming#enabled"
,
"true"
);
settings
.put(
"jdk.MethodTiming#filter"
,
"@jakarta.ws.rs.GET"
);
settings
.put(
"jdk.MethodTiming#period"
,
"10 s"
);
// Subscribe to timing events r.onEvent(
"jdk.MethodTiming"
, event -> ...);
// Set the settings, then time and trace for 60 seconds r
.setSettings(
settings
);
r
.startAsync();
Thread.sleep(60_000);
r
.stop();

520/522
JEP-520: JFR Method Timing, Tracing 
Infrastructure for method timing and tracing
via bytecode instrumentation
–Static initialisers
–Classes and annotations
$ java '-XX:StartFlightRecording:methodmethod method method----timing=::<clinit> timing=::<clinit> timing=::<clinit> timing=::<clinit>,filename=clinit.jfr' ...
$ jfr view method-timing clinit.jfr
$ jcmd <pid> JFR.start methodmethod method [email protected] [email protected] [email protected] [email protected]

521/522

522/522
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/o racle-unveils-performance-pack-for-java-8.html

Java 9: https://fossbytes.com/java-9-is-coming-rele ase-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/b enchmark-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-n ot-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-ja va-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.ht ml

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-Te mplates-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

https://www.youtube.com/watch?v=T5q72vcSjyk