Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Learning modern Java the playful way

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Learning modern Java the playful way

Staying up to date with modern Java can feel overwhelming. If you don’t have any experience with Java since Java 8 (or at all), features like structured concurrency or pattern matching might sound exciting, but also scary: “How do I even get started with that?”

Fear not! In this session Marit and Piotr will explain to you the new exciting things and also show you how to use them in your IDE, so that the next day you can start having fun and profit with modern Java in your favorite tools on your own.

Avatar for Marit van Dijk

Marit van Dijk

April 21, 2026

More Decks by Marit van Dijk

Other Decks in Programming

Transcript

  1. $ who are we Piotr Przybył @piotrprz @piotrprz.bsky.social Senior Developer

    Advocate Docker Captain Marit van Dijk @MaritvanDijk77 @maritvandijk.bsky.social Senior Developer Advocate
  2. Agenda • Various features from recent Java versions (not all

    of them, obviously) • Demos (obviously)
  3. • More Amber (pattern matching, data-oriented programming) • Loom maturing

    (Structured Concurrency, Scoped Values) • Panama + Vector API progress (performance, native interop) • Leyden groundwork (startup, footprint) • Stronger security defaults • And more
  4. • Performance (Shenandoah, Compact Object Headers) • More concurrency goodies

    (Scoped Values, revamped Structured Concurrency) • Better observability & profiling • Stuff for newbies / prototyping • And more
  5. Compact source files & Instance main methods public class HelloWorld

    { public static void main(String[] args) { System.out.println("Hello World!"); } } void main() { IO.println("Hello World!"); }
  6. final class QueryWithVector { private final String query; private final

    List<Float> vector; QueryWithVector(String query, List<Float> vector) { this.query = query; this.vector = vector; } @Override public String toString() { return "QueryWithVector[" + "query=" + query + ", " + "vector=[" + vector.getFirst() + ", --., " + vector.getLast() + ']'; } public String getQuery() { return query; } public List<Float> getVector() { return vector; } @Override public boolean equals(Object obj) { if (obj -= this) return true; if (obj -= null -| obj.getClass() -= this.getClass()) return false; var that = (QueryWithVector) obj; return Objects.equals(this.query, that.query) -& Objects.equals(this.vector, that.vector); } @Override public int hashCode() { return Objects.hash(query, vector); } } record QueryWithVector(String query, List<Float> vector) { @Override public String toString() { return "QueryWithVector[" + "query=" + query + ", " + "vector=[" + vector.getFirst() + ", --., " + vector.getLast() + ']'; } }
  7. Standard feature in Java 25 JEP 512 Compact source files

    & Instance main methods ▶ Also comes with simple IO
  8. Stream Gatherers Stream.of(...) .gather(a) [.gather(b)] [.gather(c)] .collect(...); custom intermediate operations

    Stream Gatherers - Deep Dive with the Expert: https://youtu.be/v_5SKpfkI2U Gatherers: The API Your Stream Was Missing: https://youtu.be/oVdWfU_IObY Hunting with Stream Gatherers: https://youtu.be/rvW8tu1n5x4 Extending Functional Pipelines with Gatherers: https://www.youtube.com/live/dxVDiJsyu3Y ▶
  9. Structured Concurrency • better "idioms" for multi-threaded code • synchronous

    way of thinking • help eliminate thread leaks and cancellation delays
  10. Task POST ${elasticsearch}/catalogue/_search { } “apple” POST ${elasticsearch}/catalogue/_search { }

    RRF Results: 1. … 2. … 3. … 4. … Structured Concurrency Subtask Subtask combine Results: 1. … ▶
  11. TL;DR: .open() with Joiner and Config, can (re)use thread pools,

    also platform ones Structured Concurrency try (var scope = StructuredTaskScope.open( StructuredTaskScope.Joiner.awaitAllSuccessfulOrThrow(), Config -> config .withName("myStructuredConcurrency") .withTimeout(Duration.ofSeconds(5)) .withThreadFactory(myThreadFactory))) { var subtask1 = scope.fork(() -> action(--.)); var subtask2 = scope.fork(this-:anotherAction); scope.join(); combineResults(subtask1.get(), subtask2.get()); }
  12. Lazy Constants 🧪 Preview in Java 26 JEP 526 •

    Immutable • Thread safe • Lazily evaluated ▶
  13. Lazy Constants static final LazyConstant<ObjectMapper> OBJECT_MAPPER = LazyConstant.of(ObjectMapper-:new); -/ and

    later on OBJECT_MAPPER.get()--. OBJECT_MAPPER.orElse(--.) OBJECT_MAPPER.isInitialized()
  14. Markdown Documentation Comments Standard feature in Java 23 JEP 467

    • Easier to read & write Markdown in Java Docs? Shut Up and Take My Comments! https://blog.jetbrains.com/idea/2025/04/markdown-in-java-docs-shut-up-and-take-my-comments/ ▶
  15. Pattern matching with primitive types 🧪 Preview in Java 26

    JEP 530 • Allow primitive types in all pattern contexts • Extend instanceof and switch to work with all primitive types ▶
  16. int memberDiscountPercentage(boolean isGoldMember) { return isGoldMember ? 20 : 5;

    } int itemDiscountPercentage(int items) { if (items -= 2) { return 5; } else if (items -= 3 -| items -= 4) { return 10; } else if (items -= 5) { return 20; } return 0; } int memberDiscountPercentage(boolean isGoldMember) { return switch (isGoldMember) { case true -> 20; case false -> 5; }; } int itemDiscountPercentage(int items) { return switch (items) { case 2 -> 5; case 3, 4 -> 10; case int i when i -= 5 -> 20; default -> 0; }; }
  17. $ docker exec -it es-local-dev /bin/sh -c "ps aux |

    cat" /usr/share/elasticsearch/jdk/bin/java -Des.networkaddress.cache.ttl=60 -Des.networkaddress.cache.negative.ttl=10 -XX:+AlwaysPreTouch -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true -XX:-OmitStackTraceInFastThrow -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true -Dio.netty.recycler.maxCapacityPerThread=0 --add-opens=org.apache.lucene.core/org.apache.lucene.codecs.lucene99=org.elasticsearch.server --add-opens=org.apache.lucene.core/org.apache.lucene.internal.vectorization=org.elasticsearch.server -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true -Dlog4j2.formatMsgNoLookups=true -Djava.locale.providers=CLDR -Dorg.apache.lucene.vectorization.upperJavaFeatureVersion=25 -Des.path.home=/usr/share/elasticsearch -Des.distribution.type=docker -Des.java.type=bundled JDK --enable-native-access=org.elasticsearch.nativeaccess,org.apache.lucene.core --enable-native-access=ALL-UNNAMED --illegal-native-access=deny -Des.cgroups.hierarchy.override=/ -XX:ReplayDataFile=logs/replay_pid%p.log -XX:+EnableDynamicAgentLoading -Djdk.attach.allowAttachSelf=true --patch-module=java.base=/usr/share/elasticsearch/lib/entitlement-bridge/elasticsearch-entitlement-bri dge-9.2.0.jar --add-exports=java.base/org.elasticsearch.entitlement.bridge=org.elasticsearch.entitlement,java.loggin g,java.net.http,java.naming,jdk.net -XX:+UseG1GC -Djava.io.tmpdir=/tmp/elasticsearch-12468091459950034174 --add-modules=jdk.incubator.vector -Dorg.apache.lucene.store.defaultReadAdvice=normal -Dorg.apache.lucene.store.MMapDirectory.sharedArenaMaxPermits=1 -XX:+HeapDumpOnOutOfMemoryError -XX:+ExitOnOutOfMemoryError -XX:ErrorFile=hs_err_pid%p.log -Xlog:gc*,gc+age=trace,safepoint:file=gc.log:utctime,level,pid,tags:filecount=32,filesize=64m -Xms128m -Xmx2g -XX:MaxDirectMemorySize=1073741824 -XX:G1HeapRegionSize=4m -XX:InitiatingHeapOccupancyPercent=30 -XX:G1ReservePercent=15 --module-path /usr/share/elasticsearch/lib --add-modules=jdk.net --add-modules=jdk.management.agent --add-modules=ALL-MODULE-PATH -m org.elasticsearch.server/org.elasticsearch.bootstrap.Elasticsearch ▶
  18. What did we play with? Vectors from Panama Records Structured

    Concurrency Stream Gatherers Lazy Constants Pattern Matching Compact Classes, module imports, simple IO … and more
  19. Each new Java version is: • easier • faster •

    better • and (guess what?) still free Why not use it?
  20. Thank you! Vielen Dank! Piotr Przybył @piotrprz @piotrprz.bsky.social Senior Developer

    Advocate Marit van Dijk @MaritvanDijk77 @maritvandijk.bsky.social Senior Developer Advocate