Skip to main content

Java Runtime

Writing Java code is only half the story. The other halfβ€”often the difference between a working application and a production‑grade systemβ€”is understanding how that code executes. The Java Runtime section pulls back the curtain on the JVM, the memory model, garbage collection, just‑in‑time compilation, and the concurrency machinery that your application lives on.

When you understand the runtime, you stop guessing about performance, memory, and threading. You can diagnose OutOfMemoryErrors, tune GC pauses, interpret thread dumps, and confidently choose the right JVM flags. This section is your guide from β€œit works on my machine” to β€œI know exactly what the runtime is doing.”

1. Why the Runtime Matters​

Every Java program follows the same pipeline:

Java Source Code
↓
javac Compiler
↓
Bytecode (.class)
↓
Java Runtime
↓
JVM Execution
↓
Operating System / Hardware

The Java language gives you abstraction; the runtime gives you reality. A professional engineer knows both. Runtime understanding helps you:

  • Diagnose production incidents involving memory, CPU, or latency.
  • Choose and tune garbage collectors for your workload.
  • Reason about thread safety using the Java Memory Model.
  • Optimize hot paths by understanding JIT compilation.
  • Adopt modern features like virtual threads with full awareness of their mechanics.

2. Java Runtime Architecture Overview​

The Java Runtime Environment (JRE) and the larger JDK bring together several cooperating subsystems:

Java Application
↓
Java Libraries
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ JVM Runtime β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Class Loader β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Runtime Memory Areas β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Execution Engine β”‚ β”‚
β”‚ β”‚ (Interpreter + JIT) β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Garbage Collector β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
↓
Operating System
  • Class Loader – finds and loads class files, initializes static state.
  • Runtime Memory Areas – the heap, stacks, method area, and more.
  • Execution Engine – interprets bytecode and compiles hot spots to native code.
  • Garbage Collector – reclaims memory from unreachable objects.

These subsystems work together to give Java applications portability, security, and high performance.

3. JVM Architecture​

Class Loader Subsystem​

Class loading is the gateway from bytecode to runtime representation. It proceeds in three phases:

  1. Loading – locate the class file and create a Class object.
  2. Linking – verify bytecode, prepare static fields, resolve symbolic references.
  3. Initialization – execute static initializers in a thread‑safe manner.

Key class loaders:

  • Bootstrap Class Loader – loads core Java classes (java.lang.*, etc.) from the runtime image.
  • Platform Class Loader (formerly Extension) – loads Java SE platform classes.
  • Application Class Loader – loads classes from the classpath.

Class loaders follow a delegation model: a child loader first asks its parent. This ensures core classes are never replaced and enables custom class‑loading strategies.

Runtime Data Areas​

The JVM divides memory into several regions:

Runtime Memory
β”œβ”€β”€ Heap – all object instances and arrays
β”œβ”€β”€ Java Stack – per‑thread frames holding local variables, operand stack
β”œβ”€β”€ Method Area – class metadata, constant pool, method data
β”œβ”€β”€ Metaspace – (since Java 8) class metadata in native memory
β”œβ”€β”€ PC Register – per‑thread pointer to current instruction
└── Native Method Stack – for native (JNI) code
  • Heap – the primary area managed by garbage collection. OutOfMemoryError when full.
  • Java Stack – fixed size; StackOverflowError when exceeded (deep recursion, large stack frames).
  • Metaspace – grows dynamically up to a maximum; OutOfMemoryError: Metaspace if classes are loaded excessively.

Understanding these areas lets you tune heap sizes, track metaspace growth, and interpret memory dumps.

4. Java Memory Model (JMM)​

The JMM defines how threads interact through memory. It is the specification that answers: β€œWhat value can a read see if another thread wrote to the same variable?”

The JMM describes:

  • Main memory – shared across all threads.
  • Working memory – a thread’s local cache (registers, CPU caches).
  • Visibility – when changes made by one thread become visible to others.
  • Atomicity – which operations are indivisible (e.g., reads and writes of references are atomic, but 64‑bit longs/doubles may not be without volatile).
  • Ordering – the JVM and CPU can reorder instructions for performance, but volatile and synchronized establish happens‑before relationships.

Key keywords:

  • volatile – guarantees visibility and ordering, but not atomicity for compound actions.
  • synchronized – mutual exclusion and memory visibility; all writes inside a synchronized block are visible to the next thread that enters.
  • final – properly constructed immutable objects are safe to publish without synchronization (under the JMM guarantees).

The JMM underpins the java.util.concurrent package. It’s essential for writing correct concurrent code and diagnosing heisenbugs.

5. Garbage Collection​

Garbage collection automates memory management, but its behavior directly affects throughput and latency.

Fundamentals​

The JVM considers an object reachable if it is referenced from a root set (active threads, static fields, JNI references). Unreachable objects are collected. The lifecycle: allocated β†’ reachable β†’ unreachable β†’ collected.

Common Garbage Collectors​

CollectorAlgorithmFocusBest For
Serial GCMark‑copy / mark‑compactSingle‑threaded, small heapsClient applications, small services
Parallel GCParallel mark‑copy/compactThroughputBatch jobs, high‑throughput services
G1 GCRegionalized concurrentBalanced latency/throughputServer applications, medium‑large heaps
ZGCConcurrent, load barriersUltra‑low latency (< 1ms)Large heaps, low‑pause services
Shenandoah GCConcurrent, Brooks pointersLow latencyLarge heaps, interactive applications

Choosing a collector is a trade‑off: throughput vs. pause time vs. memory overhead. The section articles dive into tuning each collector for production.

6. JIT Compiler and Execution Engine​

The execution engine runs bytecode. It starts with the interpreter, which translates bytecode one instruction at a time. As methods execute repeatedly, the Just‑In‑Time (JIT) compiler (HotSpot) kicks in.

The JIT compiler identifies β€œhot spots” and compiles them to native machine code, applying aggressive optimizations:

  • Method inlining – replaces method calls with the method body, eliminating call overhead.
  • Escape analysis – determines if an object can be allocated on the stack instead of the heap.
  • Dead code elimination – removes instructions that have no effect on program output.
  • On‑stack replacement – compiles a running interpreted loop and switches to compiled code mid‑execution.

These optimizations are why Java can match or exceed the performance of statically compiled languages for long‑running processes. Understanding them also explains why microbenchmarks need proper warmup (JMH).

7. Java Concurrency Runtime​

Java threads map to operating system threads. The runtime provides:

  • Thread lifecycle – NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED.
  • Synchronization – intrinsic locks (synchronized), Lock interfaces, ReadWriteLock.
  • Atomic classes (AtomicInteger, AtomicReference) using CAS (compare‑and‑swap) for lock‑free operations.
  • Executor framework – thread pools, ForkJoinPool, and task scheduling.

Virtual Threads (Project Loom)​

Introduced as a preview in JDK 19 and finalized in JDK 21, virtual threads are lightweight threads managed by the JVM, not the OS. They allow millions of concurrent tasks with dramatically reduced memory overhead. Virtual threads are ideal for high‑throughput I/O‑bound workloads and integrate seamlessly with existing Executor and Thread APIs. They represent a fundamental shift in how Java handles concurrency at scale.

8. JVM Monitoring and Diagnostics​

Production issues demand runtime visibility. Java ships with a suite of tools:

Command‑Line Tools​

  • jps – list JVM processes.
  • jstack – print thread stack traces; essential for deadlock detection and thread dump analysis.
  • jmap – dump heap memory; useful for leak analysis.
  • jstat – monitor GC, class loading, and JIT statistics in real time.
  • jcmd – send diagnostic commands to a running JVM.

Advanced Monitoring​

  • Java Flight Recorder (JFR) – low‑overhead event recorder for CPU, memory, I/O, and GC events.
  • Java Mission Control (JMC) – visual analyzer for JFR recordings.
  • VisualVM – lightweight profiler and heap dump analyzer.

Common Scenarios​

  • High CPU – thread dumps + profiling show which threads are spinning.
  • Memory leak – heap dumps reveal objects holding references unintentionally.
  • Thread deadlock – jstack automatically detects deadlocks.
  • Long GC pause – GC logs and JFR show pause duration and cause.

9. Java Runtime Learning Path​

TopicKey ConceptsEngineering Goal
JVM ArchitectureComponent roles, execution modelUnderstand the platform you rely on
Class LoadingDelegation, lifecycle, custom loadersDiagnose classpath and version issues
Memory ModelHeap, stack, JMM, happens‑beforeWrite correct concurrent code
Garbage CollectionAlgorithms, collectors, tuningMeet latency and throughput SLAs
Execution EngineInterpreter, JIT, optimizationsReason about performance
Concurrency RuntimeThreads, locks, virtual threadsBuild scalable, responsive applications

Deepen your runtime expertise with these guides:

  • [Java Runtime Architecture: JVM, JDK, and Execution Model Explained] – An end‑to‑end tour of the runtime stack.
  • [JVM Architecture: How Java Applications Run Inside the JVM] – Memory areas, class loading, and execution engine.
  • [Java Class Loader: Loading, Linking, and Initialization] – The complete class‑loading story.
  • [Java Memory Model (JMM): Understanding Memory Visibility and Ordering] – The concurrency contract.
  • [Java Garbage Collection: How JVM Manages Memory] – Algorithms and collection phases.
  • [JIT Compiler in Java: From Bytecode to Machine Code] – Optimizations that make Java fast.
  • [Java Concurrency Model: Threads, Locks, and Synchronization] – The threading foundation.
  • [Virtual Threads in Java: Modern Concurrency with Project Loom] – Lightweight concurrency at scale.

Master the runtime, and you master the Java platform.