Slide 1

Slide 1 text

What is Java ? Rémi Forax Java Day - June 2025

Slide 2

Slide 2 text

It starts with a mail ...

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Java is 30 years old ... but what is Java ??

Slide 5

Slide 5 text

Java the platform ? Write Once Run Anywhere

Slide 6

Slide 6 text

Java Runtime Model On heap a class defined an abstract memory layout ● No field order ● 7 primitives byte(boolean)/char/short/int/long/float/double + reference (opaque pointer to the heap, unknown size) On stack numeric ops are signed ● 4 primitives 32/64bits int/long/float/double + reference ● special unsigned variants (>>> or compareUnsigned)

Slide 7

Slide 7 text

Virtual Machine Problems at the beginning of Java – WORA : interpreters are slow – OOP: Interface / method calls are virtual ● Need runtime information

Slide 8

Slide 8 text

Hotspot VM OpenJDK VM (since Java 1.3.1) – Profiling + JITs (c1, c2) + dynamic deopt – Low level primitives atomic (VarHandle), SIMD (vector API), value types – Runtime exceptions – Virtual threads & Lightweight locks – Garbage collectors no pointer to the stack, no inner pointers 5 GCs: all generational + compacting (no fragmentation)

Slide 9

Slide 9 text

30 years of Bytecode The bytecode is really really stable – New optional attributes ● GenericSignature, LocalVariableTypeTable, Runtime*Annotations ● StackMapTable, Module, NestHost, Record, etc ● LoadableDescriptors (valhalla ??) – New constants ● Constant Dynamic, MethodHandle, MethodType, Module, Package – One new opcode ● invokedynamic

Slide 10

Slide 10 text

JVM languages Statically typed languages – Java, Kotlin, Scala Dynamically typed languages – Groovy, Clojure Other languages runtimes – JRuby / TruffleRuby for Ruby – Rhino, Nashorn, lilijs for JavaScript – GraalJS for JS – GraalPython for Python

Slide 11

Slide 11 text

Java the language ?

Slide 12

Slide 12 text

Java the language ? Write Once Run Anywhere ... forever

Slide 13

Slide 13 text

Java the language ? Write Once Run Anywhere ... forever <==> Composition at Scale

Slide 14

Slide 14 text

Composition at Scale Your Application Library 1 Library 2 Library 3 Library 4

Slide 15

Slide 15 text

Don’t of Java Clash with the composition at scale Cases of function coloring* – Rust lifetime attributes (we have GCs) – Async/Reactive method (we have virtual threads) – Use class/type for errors (we have exceptions) and checked exceptions are bad :( * https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/

Slide 16

Slide 16 text

API backward compatibility Java provides binary backward compatibility – Unlike C, C++, Rust, Python, or JS Composition of libraries written with different versions of the language – No: Python 2 vs Python 3

Slide 17

Slide 17 text

Java versions Softwares change … Java too 4 ages: ● Java 1: OOP (1995) ● Java 5: Generics (2004) ● Java 8: Lambda (2014) ● Java 21: Pattern Matching (2023)

Slide 18

Slide 18 text

Java versions for ... For Libraries – OOP (1995) – Generics (2004) For Applications – Lambda (2014) – Pattern Matching (2024)

Slide 19

Slide 19 text

Library vs Application Not the same constraints – Library : Object Oriented Programming ● Must be composable/upgradable fearlessly ● Code should be fast – Application : Data Oriented Programming ● Business requirements change ● Code should be readable

Slide 20

Slide 20 text

Libraries

Slide 21

Slide 21 text

Library API Your Application Library 1 Library 2 Library 3 Library 4 A P I A P I API API Applications are written against library APIs

Slide 22

Slide 22 text

Object Oriented Programming Interface <=> API – or any public methods of any public classes Java in the beginning – Everything is an API => too much OOP ● Also everything has a name

Slide 23

Slide 23 text

Inheritance ? Inheritance is really bad ! package lib2; class MyAPI extends lib3.AnotherAPI { // oops, my API is not stable ! }

Slide 24

Slide 24 text

API with inheritance Your Application Library 1 Library 2 Library 3 Library 4 A P I A P API API API The API of Library 2 is NOT stable !

Slide 25

Slide 25 text

Applications

Slide 26

Slide 26 text

Dependencies For a specific task, prefer to use an existing library instead of your own code apart if ● The code is trivial ● The library has a bus factor of 1 ● The library code is awful LLMs generated codes using too many dependencies !!

Slide 27

Slide 27 text

Functional first Use Immutable data – String, enums, records Use Unmodifiable collections – List.of()/List.copyOf(), Set.of()/Set.copyOf(), Map.of()/Map.copyOf() Share code using static methods – No abstract class, please !

Slide 28

Slide 28 text

Keep it simple No OOP where it’s not necessary – Behavior should be localized in one place ● Use pattern matching – No big hierarchy (unless you need it) ● Interfaces are not central to the design – just a lightweight abstraction (A | B) – sealed interfaces should be empty

Slide 29

Slide 29 text

Example (for an application) sealed interface Vehicle {} record Car() implements Vehicle {} record Bus() implements Vehicle {} Tax computeTax(Vehicle v) { return switch(vehicle) { case Car c → … case Bus b → ... }; } interface Vehicle { Tax computeTax(); } record Car() implements Vehicle { Tax computeTax() { … } } record Bus() implements Vehicle { Tax computeTax() { … } } Bad : open hierarchy Good : pattern matching

Slide 30

Slide 30 text

Hide states behind functions Mutate state only for perf reason – e.g. StringBuilder vs String But wrap it into a pure function String interpolate(String pattern, Object… values) { // use StringBuilder here }

Slide 31

Slide 31 text

Pure function <=> Immutable class Those two codes are equivalent record Interpolator(String pattern) { String interpolate(Object… values) { } } And String interpolate(String pattern, Object… values) { }

Slide 32

Slide 32 text

Encapsulation : member modifiers “public” and “private” are enough ! Use “package private” for – Sharing implementation details – Testing “protected” is useless (and part of the API !)

Slide 33

Slide 33 text

No global ! static non-final field are evil ! Code using globals – can not be tested – value dependencies can not be tracked

Slide 34

Slide 34 text

Ensure Objects safety Parse don’t validate ! Don’t create an object with the wrong values ● Check BEFORE creating the object Public methods should check their parameters – Fail fast if unexpected values – Use Objects.requireNonNull, null should not propagate – Don’t play god, no default value, make it explicit

Slide 35

Slide 35 text

Ensure Object safety (2) Constructors should only initialize values + value checks Use static factory methods – If it is more complicated, e.g a constructor should not throw IOException !

Slide 36

Slide 36 text

No overload / one constructor Not more than one method/constructor, – Otherwise, I must read the doc => Lead to composition with fear PrintStream.println() is okay – All overloads have the same semantics

Slide 37

Slide 37 text

Dependency injection It makes the code less explicit Okayish – for framework objects (Service, Data repository, etc) – constructor injection only !

Slide 38

Slide 38 text

Exceptions are not pokemon You do not have to catch them all ! Only catch an exception – At the bottom of the stack – If you can recover from it ● Or to re-throw another exception (with the cause)

Slide 39

Slide 39 text

Streams Use streams to make the code more readable but stream stacktraces are terrible ● Lambdas taken as parameter should have a small stacktrace Performance – Do not use flatMap – Use stateful operations with caution ● distinct(), sorted()

Slide 40

Slide 40 text

TLDR;

Slide 41

Slide 41 text

What is Java ? Composition at scale Libraries should use OOP Application should use DOP – Functional first + encapsulate mutable state – Ensure object safety – Keep it simple and explicit

Slide 42

Slide 42 text

Futures of Java

Slide 43

Slide 43 text

Language Features missing ? Destructuring of Record (like tuples) record MinMax(int min, int max) { } MinMax computeMinMax(int... array} { … } var (min, max) = computeMinMax(1, 7, -3); var (_, max2) = computeMinMax(1, 7, -3); New record instance by name var minMax = MinMax { .max = 17, .min = 12 }; var minMax2 = MinMax { .min = 10, minMax... }; Destructuring by name var {.max, .min} = computeMinMax(1, 7, -3);

Slide 44

Slide 44 text

In the pipeline OpenJDK projects Panama Simple C bridge : j.l.foreign + jextract Leyden Improve startup / warmup time : cache objects / metadata Babylon Code reflection to CUDA, to ONXX Valhalla Encapsulation/Abstraction of small objects for free Nullness Emotion (aka Complex!) Early access at https://jdk.java.net

Slide 45

Slide 45 text

No content