AnaMariaMihalceanu1
47 views
48 slides
May 22, 2024
Slide 1 of 48
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
About This Presentation
Slides for Voxxed Days Brussels
Size: 2.49 MB
Language: en
Added: May 22, 2024
Slides: 48 pages
Slide Content
Java 22 and Beyond
A Roadmap of Innovations
Java Champion Alumni, Certified Architect
Senior Developer Advocate at Oracle
Passionate about solving complex scenarios
involving Java and Kubernetes.
ammbra1508.mastodon.social ammbra1508
“The only way you can predict the
future is to build it"
Alan Kay
Download and give it try: https://jdk.java.net/22/
6-month Release Cadence
Project Summary Pain point “Obvious"
Competition
Amber Right-sizing language ceremony
“Java is too verbose"
“Java is hard to teach"
C#, Kotlin
Babylon
Foreign programming model
interop
“Using GPUs is too hard" LinQ, Julia
Leyden Faster startup and warmup “Java starts up too slowly" Go
Loom Lightweight concurrency “Threads are too expensive, don’t scale" Go, Elixir
Panama
Native code and memory interop
SIMD Vector support
“Using native libraries is too hard"
“Numeric loops are too slow"
Python, C
Valhalla
Value types and specialized
generics
“Cache misses are too expensive"
“Generics and primitives don’t mix"
C, C#
ZGC Sub-millisecond GC pauses “GC pauses are too long" C, Rust
Java in the Small
As a result, it is easy to forget about the “small" programs
Java has been historically
successful in “big" systems
And we all start small
But, we want Java
to be successful
for small things too
•OOP concepts such as access control and static-ness
should not overwhelm your first (or any small) program
•The “on ramp" should lead smoothly onto the highway
“Paving the On Ramp"
A Simplified Begining
Project Amber
Towards a Simplified Beginning
// HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Use jshell for fast prototyping Java code
Launch via single file execution (since JDK 11)
java HelloWorld.java
JEP 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
Class declaration no longer required
main is not necessarily public static
String[] args not declared if not used further
Invocation Order when Selecting Main
☕ A static void main(String[] args) method of non-private access in the launched class.
☕ A static void main() method with non-private access in the launched class.
☕ A non-private void main(String[] args) instance method in the launched class/inherited from a
superclass.
☕ A non-private void main() instance method in the launched class or inherited from a superclass.
One Command to Launch Them All
// HelloWorld.java
class HelloWorld {
void main() {
Helper.run();
}
}
◦
// Helper.java
import static java.lang.System.out;
So you want to know more…
☕ JEP 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
☕ Script Java Easily in 21 and Beyond - Inside Java Newscast #49
☕JEP 458: Launch Multi-File Source-Code Programs
☕Does Java 22 Kill Build Tools? - Inside Java Newscast #63
☕JEP 477: Implicitly Declared Classes and Instance Main Methods (Third Preview)
Thoughtful Evolution of Java
Language Features
Project Amber
Wrapup Data Modeling
☕ A sender can do a nice gesture and offer a gift.
☕ A gift can only be either a postcard or add to it
one of the following: an online coupon, buy an
experience or a material present.
☕ A postcard does not have an associated cost, all
the other 3 types of products have a price.
☕A sender can never send 2 postcards as a gift.
☕ An online coupon has an expiry date.
☕ A present can be placed inside a box.
☕ A coupon could be bought for sharing an
experience too.
Wrapup Data Modeling Detailed
☕ Sealed types limit which subtypes can directly
extend/implement them.
public sealed interface Intention
permits Coupon, Experience,
Present, Postcard {}
public sealed class Experience
implements Intention
permits Coupon {}
☕ Present,Postcard are records.
☕ Coupon extends Experience.
☕ Represent Gift using composite patterns.
Inheritance and Constructor Chaining
public final class Coupon extends Experience implements Intention {
private final LocalDate expiringOn;
private static double verifyPositive(double price) {
if (price < 0) {
throw new IllegalArgumentException("Price cannot be negative");
}
return price;
}
}
Constructor chaining is enforced in subclass.
Statements Before super(…) (in preview)
public final class Coupon extends Experience implements Intention {
private final LocalDate expiringOn;
public Coupon(double price, LocalDate expiringOn, Currency currency) {
if (price < 0) {
throw new IllegalArgumentException("Price cannot be negative");
}
super(price, currency);
this.expiringOn = expiringOn;
}
}
JEP 447: Statements before super(...) (Preview)
Validate superclass constructor arguments
Prepare superclass constructor arguments
Share superclass constructor arguments
Wrapup Expressive Data Modeling
☕ Sealed types limit which subtypes can directly
extend/implement them.
public sealed interface Intention
permits Coupon, Experience,
Present, Postcard {
//…
}
☕ Coupon,Experience,Present,Postcard
are records.
☕ Represent Gift using nested record patterns.
Record Patterns and Exhaustive Switch
JSONObject process(Gift gift, Choice choice) {
return switch (gift) {
case Gift(Postcard p, Postcard p2) -> new JSONObject(p);
case Gift(Postcard p, Coupon c) when (c.price() == 0.0) -> new JSONObject(p);
case Gift(Postcard p, Experience e) when (e.price() == 0.0) -> new JSONObject(p);
case Gift(Postcard p, Present pr) when (pr.itemPrice() == 0.0) -> new JSONObject(p);
case Gift(Postcard p, Experience e) -> gift.merge(choice.name().toLowerCase());
case Gift(Postcard p, Present pr) -> gift.merge(choice.name().toLowerCase());
case Gift(Postcard p, Coupon c) -> gift.merge(choice.name().toLowerCase());
};
}
Code Readability and Lower Error Chances
JSONObject process(Gift gift, Choice choice) {
return switch (gift) {
case Gift(Postcard p, Postcard _) -> new JSONObject(p);
case Gift(Postcard p, Coupon c) when (c.price() == 0.0) -> new JSONObject(p);
case Gift(Postcard p, Experience e) when (e.price() == 0.0) -> new JSONObject(p);
case Gift(Postcard p, Present pr) when (pr.itemPrice() == 0.0) -> new JSONObject(p);
case Gift(_, Coupon _), Gift(_, Experience _), Gift(_, Present _) -> {
String option = choice.name().toLowerCase();
yield gift.merge(option);
}
};
}
JEP 456: Unnamed Variables & Patterns
So You Want To Know More…
☕ Clean Application Development with Records, Sealed Classes and Pattern Matching (2022)
☕ Java Records are "Trusted" and Consequently Faster
☕State of Pattern Matching with Brian Goetz (2022)
☕ Pattern Matching in the Java Object Model
☕ Patterns: Exhaustiveness, Unconditionality, and Remainder
☕Uniform handling of failure in switch
Fundamental Changes to
Achieve Your Application Goals
Core Libraries
Compiling and Launching a Java Program
IDE
javac java
.java source
file
bytecode .class
file
Program running
The New Class-File API (in preview)
☕ A stable Java API for analyzing and manipulating bytecode.
☕ An API always-up-to-date with the JDK version.
☕ Frameworks that use this API can easily update to a newer JDK version.
JEP 457: Class-File API (Preview)
So You Want To Know More…
☕ A Classfile API for the JDK (JVMLS 2023, Brian Goetz)
☕ New Class-File API will make Java Updates easier - Inside Java Newscast #56
Unfulfilled Streams Operations
☕ Streams API has a fixed set of intermediate operations.
List<String> letters = Arrays.asList("A","B","C","D","E","F","G","H");
int size = 3;
☕ Some intermediate operations are missing: sliding windows, take-while-including, fixed grouping, scanning, etc.
Enter Gatherers API (in preview)
☕ A generalization for intermediate operations java.util.stream.Gatherer
☕ A new intermediate stream operation to process elements of a stream: Stream::gather(Gatherer)
☕ A few implementations, e.g. Gatherers.fold(…), Gatherers.windowFixed(…).
☕ A way to compose gathererers source.gather(a.andThen(b).andThen(c)).collect(...)
Integrator (mandatory)
☕ Accepts (state, element, downstream)
☕Integrates element into state
•to update gatherer’s private state object
•to emit 0+ element(s) to downstream
Gatherers Components
Initializer (optional)
☕Creates private state object
Combiner (optional)
☕Can evaluate the gatherer in parallel
Finisher (optional)
☕Accepts (state, downstream)
☕Invoked when no more elements can be
consumed
☕Emits element(s) to downstream
So You Want To Know More…
☕ Teaching Old Streams New Tricks (Devoxx Belgium 2023, Viktor Klang)
☕ Better Java Streams with Gatherers - Inside Java Newscast #57
Faster, Safer, Easier
Java-to-Native Interoperability
Project Panama
JNI and Reduced latency in G1GC
☕ JNI includes critical accessor functions.
☕ The JVM must not move a Java thread that is in a critical region
☕ Lock an object in place as the GC moves other objects (pinning).
From Unsafe to proper handling
Create an object without
running its constructor
Directly access hardware
features or the CPU
Manually manage off-heap
memory
String payload = "22";
var functionName = "strlen";
try (var arena = Arena.ofConfined()) {
var segment = arena.allocateFrom(payload);
int result = (int) funcHandle.invoke(segment);
System.out.println("The answer is " + result);
}
Foreign Function & Memory API
Get lookup object for string library
Get method handler for strlen
Invoke foreign function
Allocate the required foreign
memory
So You Want To Know More
☕ Evacuation Failure and Object Pinning
☕Download jextract binaries
☕Samples for jextract
☕Learn how to write fast Java code with the Vector API - JEP Café #18
☕Published content on Panama project: https://inside.java/tag/panama
Concurrent Programming without
Thread Leaks and Cancelation Delays
Project Loom
Virtual Threads Under the Hood
A thread managed
by JVM scheduler
can get a task
assigned by you.
Java scheduler
assigns the virtual
thread to platform
thread(s).
Virtual thread asks platform
thread(s) to perform the task.
If a virtual thread has some blocking
I/O operation, it will be detached from
the platform thread.
Another virtual thread is assigned to the
platform thread so that the platform thread
stays in a running state
var offer1 = scope.fork(() -> readOffer1(refPrice, boxPrice));
var offer2 = scope.fork(() -> readOffer2(refPrice, boxPrice));
var offer3 = scope.fork(() -> readOffer3(refPrice, boxPrice));
var offer4 = scope.fork(() -> readOffer4(refPrice, boxPrice));
scope.join();
Present quickPresent = scope.result();
return quickPresent;
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
Obtain a present fast from the available offers
☕ Create relationship between threads
☕ Forked tasks are children of the scope
☕ Success/failure policy can be defined across
all children.
☕ Return the result of the first subtask that
completed with a result.
var offer1 = scope.fork(() -> readOffer1(refPrice, boxPrice));
var offer2 = scope.fork(() -> readOffer2(refPrice, boxPrice));
var offer3 = scope.fork(() -> readOffer3(refPrice, boxPrice));
var offer4 = scope.fork(() -> readOffer4(refPrice, boxPrice));
scope.join();
Present quickPresent = scope.result();
return quickPresent;
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
Obtain a present fast from the available offers
☕ Create relationship between threads
☕ Forked tasks are children of the scope
☕ Success/failure policy can be defined across
all children.
☕ Return the result of the first subtask that
completed with a result.
☕ Thread-dumps capture transparently the
relationship between threads.
Benefits for High Scaling Applications
Higher throughput with fewer CPU
operations when having high number
concurrent requests.
When having blocking calls, virtual threads
will go in a waiting state until they receive
data.
//in Wrapup record
ScopedValue.where(VALID_REQUEST, Choice.EXPERIENCE)
.call(() -> findOffer(data.itemPrice()));
// in Experience record
public Experience {
if (!VALID_REQUEST.isBound()) {
throw new IllegalStateException("not bound");
} else if (!VALID_REQUEST.get()
.equals(Choice.EXPERIENCE)) {
throw new
IllegalStateException(VALID_REQUEST.get());
}
}
//…
Experience Scoped Values
Find the best in price experience
☕ Best experience for a valid request
☕ Simplify reasoning about data flow
public static class ExperienceScope
extends StructuredTaskScope<Experience> {
//…
try (var scope = new Experience.ExperienceScope()) {
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//…
Experience Scoped Values
Find the best in price experience
☕ Best experience for a valid request
☕ Simplify reasoning about data flow
☕ The lifetime of shared data is visible from
code structure.
☕ Data shared by a caller can be retrieved
only by legitimate callees.
☕ Performance through immutable shared
data.
So You Want To Know More
☕ Structured Concurrency
☕ On Parallelism and Concurrency
☕ Java 20 - From ThreadLocal to ScopedValue with Loom Full Tutorial - JEP Café #16
☕JEP 464: Scoped Values (Second Preview)
Stay Tuned for More!
Inside.javaDev.java youtube.com/java