Java — Reference
Source: https://docs.oracle.com/en/java/javase/25/
Java
- Created: 1995 by James Gosling at Sun Microsystems; now stewarded by Oracle and the OpenJDK community
- Latest stable: JDK 26 (2026-03-17, non-LTS); JDK 25 (LTS) (2025-09-16) — recommended for production
- Paradigms: object-oriented (class-based), imperative; functional features since 8 (lambdas, streams); pattern matching since 21; records and sealed classes since 16/17
- Typing: static, nominal, mostly invariant generics with use-site variance via wildcards (
? extends,? super); type erasure at runtime - Memory: garbage collected. JDK 25 ships ZGC (generational, sub-millisecond pauses), G1 (default), Shenandoah, Parallel, Serial, Epsilon (no-op for benchmarking)
- Compilation: AOT to bytecode (
javac→.class) → JIT-compiled at runtime by HotSpot’s C1/C2 (or GraalVM). AOT-to-native via GraalVMnative-imageand Project Leyden. - Primary domains: enterprise backends, Android (Kotlin/Java on ART), big data (Hadoop, Spark, Flink, Kafka), build tooling, financial systems, embedded (Java ME), IDEs (IntelliJ, Eclipse, NetBeans)
- Official docs: https://docs.oracle.com/en/java/javase/25/
At a glance
- JDK distributions: Oracle JDK, OpenJDK builds (Eclipse Temurin / Adoptium, Amazon Corretto, Azul Zulu, Microsoft Build of OpenJDK, BellSoft Liberica, SapMachine, GraalVM, IBM Semeru). All built from OpenJDK source.
- Release cadence: 6-month feature releases (JEP-process driven), LTS every 2 years (8, 11, 17, 21, 25, …).
- JVM is multi-language: Kotlin, Scala, Clojure, Groovy, JRuby, Jython, plus polyglot via GraalVM (JS, Python, Ruby, R, WASM).
- Governance: OpenJDK Community + Java Community Process (JCP) for JSRs; JEPs (JDK Enhancement Proposals) drive features.
Getting started
Install:
- Recommended: SDKMAN! (
sdk install java 25.0.1-tem) — switches JDKs per shell. - Direct: Eclipse Temurin (https://adoptium.net), Microsoft Build of OpenJDK, Amazon Corretto, Oracle JDK.
- Windows:
winget install EclipseAdoptium.Temurin.25.JDK. macOS:brew install --cask temurin@25.
Hello world (single file, since JEP 330 / 477):
// Hello.java — runnable directly with `java Hello.java` (no compile step) since JDK 11+
void main() { // implicit class & no-arg main since JDK 25 (JEP 512)
IO.println("Hello, world!");
}Classic form:
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}Project layout (Maven / Gradle convention):
myapp/
pom.xml # or build.gradle(.kts)
src/
main/
java/
com/example/App.java
resources/
test/
java/
com/example/AppTest.java
target/ # Maven; build/ for Gradle
Build tools:
- Maven (XML, declarative, ubiquitous in enterprise) —
mvn package. - Gradle (Groovy or Kotlin DSL, programmatic) —
./gradlew build. Default for Android. - Bazel (Google’s, mono-repo).
- Newer: Mill, Bld.
- JDK 25 added the JEP 512 launcher with implicit imports; you can ship single-file scripts.
REPL: jshell (since JDK 9). Online: https://dev.java/playground/
Basics
Primitives: byte (8), short (16), int (32), long (64), float (32), double (64), char (UTF-16 code unit), boolean. Boxed: Integer, Long, Double, etc. Value classes (Project Valhalla) are landing in preview.
Variables / scope: lexically scoped. var (JDK 10+) for local-variable type inference (NOT for fields, params, returns). final for immutable bindings.
var users = new ArrayList<String>(); // inferred ArrayList<String>
final int max = 10;Control flow: if/else, for, enhanced for (T x : iterable), while, do/while, switch (statement and expression form), try/catch/finally, try-with-resources. Pattern matching for switch (JEP 441, JDK 21):
String describe(Object o) {
return switch (o) {
case Integer i when i > 0 -> "positive int " + i;
case String s -> "string: " + s;
case null -> "null!";
default -> "other";
};
}Functions: methods belong to classes. Lambdas (since 8) implement functional interfaces (one abstract method).
Function<Integer, Integer> square = x -> x * x;
List<String> upper = names.stream().map(String::toUpperCase).toList();Method references: Class::method, instance::method, Class::new.
Strings: String is immutable, UTF-16 internally (compact strings since 9 use Latin-1 when possible). Text blocks """...""" (JDK 15). String templates were withdrawn (JEP 459 retracted) — no native interpolation as of JDK 25; use String.format or formatted.
Built-in collections: List, Set, Map, Queue, Deque interfaces with ArrayList, LinkedList, HashMap, LinkedHashMap, TreeMap, HashSet, TreeSet, ArrayDeque. Immutable factories: List.of(), Map.of(), Set.of(). Sequenced collections (JDK 21): SequencedCollection, SequencedSet, SequencedMap with getFirst/getLast/reversed.
Intermediate
Type system:
- Generics with invariant type parameters; use-site variance via
? extends T(covariant) /? super T(contravariant). - Erased at runtime (no
T.classdirectly — passClass<T>token). - Bounded type params:
<T extends Comparable<T>>. - Records (JDK 16):
public record Point(int x, int y) {}— immutable data carriers with autoequals/hashCode/toString. - Sealed classes (JDK 17):
sealed interface Shape permits Circle, Square {}— exhaustive pattern matching. - Pattern matching for
instanceof(JDK 16):if (o instanceof String s) { ... }.
Modules / packages: package = directory; module = JEP 261 (JDK 9) module-info.java declaring requires/exports/opens. Most apps still use the classpath, not the module path — module system is mostly used by the JDK itself and by some frameworks.
Errors: checked vs unchecked exceptions — checked must be declared with throws or caught. RuntimeException and Error are unchecked. Try-with-resources auto-closes AutoCloseable.
try (var f = Files.newBufferedReader(path)) { ... } // auto-closeConcurrency primitives:
Thread,Runnable,Callable<V>,Future<V>,CompletableFuture<V>.java.util.concurrent:ExecutorService,ForkJoinPool,Semaphore,CountDownLatch,CyclicBarrier,ConcurrentHashMap,BlockingQueue.synchronized,volatile,Lock,ReentrantLock,StampedLock.- Virtual threads (JEP 444, JDK 21) — millions of cheap green threads on a small carrier-thread pool.
Thread.startVirtualThread(...),Executors.newVirtualThreadPerTaskExecutor(). - Structured concurrency (JEP 480, finalizing):
StructuredTaskScopefor parent-child task lifetimes. - Scoped values (JEP 446): immutable per-thread context, designed for virtual threads.
File I/O / networking: java.nio.file.Path/Files/FileChannel, java.net.http.HttpClient (HTTP/2 + WebSocket), Socket/ServerSocket, Selector for non-blocking I/O.
Stdlib highlights: java.time (JSR-310 immutable date/time), java.util.stream, java.util.function, java.lang.invoke (MethodHandles), java.util.concurrent, java.security, java.net.http, java.lang.foreign (Panama FFM, JDK 22).
Advanced
Memory model & GC:
- JMM (JLS Ch. 17) defines happens-before, volatile semantics, final-field freezing.
- Default GC: G1 (low-pause, regional). ZGC (generational since JDK 21, sub-ms pauses, multi-TB heaps). Shenandoah (Red Hat). Parallel (throughput-oriented). Serial (single-threaded). Epsilon (no-op).
- Tune:
-Xms/-Xmx(heap size),-XX:+UseZGC,-XX:MaxGCPauseMillis=N,-XX:NewRatio,-XX:SurvivorRatio. Inspect:-Xlog:gc*:file=gc.log. - Tools: JFR (Flight Recorder, free since 11), Mission Control (JMC),
jstat,jmap,jhsdb, async-profiler, Eclipse MAT.
Concurrency / parallelism deep dive:
- HotSpot biased locking removed in 15. Lightweight + heavyweight (monitor) locks remain.
VarHandle(JDK 9) — typed, mode-aware (getVolatile,compareAndSet,getAcquire/setRelease).- Fork/Join uses work-stealing deques.
- Virtual threads pin to carrier thread inside
synchronized; preferReentrantLockin pinning-sensitive code.
FFI / interop:
- Project Panama Foreign Function & Memory API (
java.lang.foreign, finalized JDK 22) — modern replacement for JNI.Arena,MemorySegment,Linker,FunctionDescriptor.jextractgenerates bindings from C headers. - JNI still works but is verbose and unsafe.
- GraalVM Polyglot API: call JS, Python, Ruby, WASM from Java.
Reflection: java.lang.reflect (Class, Method, Field, Constructor, Modifier). MethodHandles (java.lang.invoke) — faster, type-safe, supports invokedynamic. Records expose RecordComponent[].
Performance tuning:
- JIT: HotSpot tiered compilation (Interpreter → C1 → C2).
-XX:+PrintCompilation,-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly(needs hsdis). - JFR:
-XX:StartFlightRecording=duration=60s,filename=app.jfr. Open in JMC. - Profilers: async-profiler (JFR-aware, low overhead), VisualVM, YourKit, JProfiler.
- Microbenchmarks: JMH — the only correct way to benchmark JVM code.
- AppCDS / CDS: pre-share class metadata (
-XX:ArchiveClassesAtExit). - AOT: GraalVM
native-image, Project Leyden’s--AOTcache.
God mode
Bytecode (javap, ASM, ByteBuddy):
javap -p -c -v Foo.class # disassembleBytecode is stack-based, ~200 opcodes (iload, invokevirtual, invokedynamic). ASM is the low-level lib; ByteBuddy is the friendly wrapper used by Mockito, Hibernate, Datadog agent.
Unsafe (sun.misc.Unsafe / jdk.internal.misc.Unsafe): off-heap memory, low-level CAS, raw object construction. Encapsulated since JDK 9; access requires --add-opens. Replacements:
VarHandlefor atomic ops.MemorySegment(Panama) for off-heap memory.Lookup.defineHiddenClassfor runtime class definition.
Java agents & instrumentation:
java.lang.instrument.Instrumentation— bytecode rewriting at load or runtime.- Premain agent:
-javaagent:agent.jar. - Dynamic attach:
VirtualMachine.attach(pid).loadAgent(...). - Used by: Datadog APM, New Relic, Mockito, IntelliJ debugger, JaCoCo coverage.
MethodHandle / invokedynamic: the bytecode behind lambdas, string concat (StringConcatFactory), and pattern matching dispatch. Build dynamic call sites with LambdaMetafactory.
GraalVM native-image: AOT compile JVM bytecode to a native binary. Closed-world assumption — reflection / dynamic class loading needs config. Used by Quarkus, Micronaut, Spring Native, Helidon, Picocli for fast-startup CLIs.
Project Leyden: AOT class loading + linking + (eventually) AOT-compiled native code without GraalVM’s closed-world restriction.
Project Valhalla: value classes + primitive classes + universal generics — flatten layout, eliminate boxing. In preview.
Project Loom: virtual threads (delivered) + structured concurrency + scoped values.
Project Panama: FFM API (delivered) + Vector API (incubator: SIMD intrinsics).
Custom build phases / annotation processors:
javax.annotation.processing— generate code at compile time. Used by Lombok (legacy hack via internal APIs), AutoValue, Dagger, Immutables, MapStruct.- Maven plugins:
maven-compiler-pluginconfigures processors. Gradle:annotationProcessorconfiguration.
Embedding the JVM: Invocation API (JNI_CreateJavaVM) or Panama-based approach. libjvm.so is the runtime; you load it from C/C++.
Idioms & style
- Naming:
PascalCasefor classes/interfaces,camelCasefor methods/vars,SCREAMING_SNAKEfor constants. Packageslowercase.dotted.like.com.example. - Formatters:
google-java-format(canonical), Spotless (build-tool wrapper), Eclipse formatter, IntelliJ built-in. - Linters: Checkstyle, SpotBugs (formerly FindBugs), Error Prone (Google, plugs into javac), PMD, SonarQube/SonarLint.
- Style guides: Oracle Code Conventions (1999, dated), Google Java Style (https://google.github.io/styleguide/javaguide.html), team-specific.
- Idiomatic patterns:
- Records for data carriers; sealed interfaces + records for sum types.
Optional<T>for “may return null” returns (NOT for fields/params).- Immutability where possible —
finalfields,List.copyOf(...). - Streams for collection pipelines, but loops are fine when clearer.
- Try-with-resources for any
AutoCloseable. - Builder pattern (
@Builderfrom Lombok or hand-rolled) for big constructors. - Dependency injection (Spring, Guice, Dagger, Quarkus CDI, Micronaut).
- Reviewer tells: mutable static state, swallowing exceptions, raw types (
Listinstead ofList<String>),nullreturns instead ofOptional/empty collection,equals/hashCodemismatch, missing@Override, abuse of inheritance over composition.
Ecosystem
| Domain | Tools |
|---|---|
| Web frameworks | Spring Boot, Quarkus, Micronaut, Helidon, Vert.x, Javalin, Play |
| ORM / Persistence | Hibernate / JPA, jOOQ, MyBatis, Spring Data, EclipseLink, Ebean |
| Testing | JUnit 5 (Jupiter), TestNG, Mockito, AssertJ, Hamcrest, Testcontainers, ArchUnit |
| Build | Maven, Gradle, Bazel, Mill, Bld |
| Big Data / Stream | Apache Spark, Flink, Kafka, Beam, Hadoop, Cassandra, Elasticsearch, Lucene |
| Web servers | Tomcat, Jetty, Undertow, Netty (async), Helidon Nima (virtual-thread native) |
| Microservice frameworks | Spring Cloud, Quarkus, Micronaut, Helidon |
| Observability | Micrometer, OpenTelemetry Java agent, JFR, Datadog, New Relic |
| Docs | Javadoc (built-in), AsciiDoctor (asciidoclet) |
| Native / cloud | GraalVM Native Image, Spring Native, Quarkus, Buildpacks, Jib, Liquibase, Flyway |
| Notable users | every bank ever, Netflix, LinkedIn, Twitter (originally), Amazon, Google (Android, internal), Alibaba (Dragonwell JDK), Uber, Airbnb |
Gotchas
- Type erasure:
new T[10]doesn’t work; can’t overload onList<String>vsList<Integer>;instanceof List<String>is illegal. - Autoboxing:
Longvslongin==—==on boxed types compares references. Always use.equals()or unbox. Integercache:Integer.valueOf(127) == Integer.valueOf(127)is true,128 == 128is false.- Checked exceptions in lambdas:
Stream.map(x -> Files.readString(p))won’t compile — wrap inFunctionthat re-throws as unchecked. Dateis awful — mutable, broken timezone handling. Usejava.time(Instant,LocalDate,ZonedDateTime).equals/hashCodecontract — override both or neither. Records do it for you.HashMapthread safety — none. UseConcurrentHashMap.Collections.synchronizedList(...)doesn’t synchronize iteration — wrap insynchronized(list) { ... }block.- Static initialization order can deadlock between classes.
String.intern()can fill PermGen / metaspace.finalize()is deprecated; useCleaneror try-with-resources.- Modular access: since JDK 9,
setAccessible(true)on JDK internals requires--add-opens. Lombok and similar tools paper over this. Optionalis notSerializable; never use as a field type.- Newcomers from Python: verbose, no top-level functions (until JEP 512 in 25), checked exceptions feel painful, generics are erased so reflection-based libs need
TypeReference/TypeToken. - Newcomers from C#: Java has no properties (write
getX/setX), no operator overloading, noout/ref, no LINQ syntax (use Streams), generics are erased not reified.
Citations
- Oracle Java SE docs (25): https://docs.oracle.com/en/java/javase/25/
- Java Language Specification: https://docs.oracle.com/javase/specs/jls/se25/html/index.html
- Java Virtual Machine Specification: https://docs.oracle.com/javase/specs/jvms/se25/html/index.html
- OpenJDK: https://openjdk.org/
- JEP index: https://openjdk.org/jeps/0
- JEP 444 (virtual threads): https://openjdk.org/jeps/444
- JEP 480 (structured concurrency): https://openjdk.org/jeps/480
- JEP 512 (compact source files / instance main): https://openjdk.org/jeps/512
- Foreign Function & Memory API (JEP 454): https://openjdk.org/jeps/454
- Google Java Style: https://google.github.io/styleguide/javaguide.html
- GraalVM Native Image: https://www.graalvm.org/latest/reference-manual/native-image/
- ByteBuddy: https://bytebuddy.net/
- Adoptium / Temurin: https://adoptium.net/
- Wikipedia (version history reference): https://en.wikipedia.org/wiki/Java_version_history