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